- Шпаргалка по установке CUDA, cuDNN, Tensorflow и PyTorch на Windows 10
- Краткий алгоритм установки Tensorflow и PyTorch
- Подготовка к установке
- Установка CUDA и cuDNN
- Устанавливаем Tensorflow
- Устанавливаем PyTorch
- Итого
- CUDA под Windows: советы в начале работы
- Что необходимо для работы с CUDA
- Как создавать проекты CUDA в Visual Studio и запускать примеры из книги
- Сообщения об ошибках
- Решение проблемы «Видеодрайвер nVidia перестал отвечать и был успешно восстановлен»
- Читайте также
- Комментарии
- Параллельное программирование с CUDA. Часть 1: Введение
- Еще одна статья о CUDA — зачем?
- Содержание
- Задержка vs пропускная способность
- Базовые понятия и термины CUDA
- Основные этапы CUDA-программы
- Пишем первую программу на CUDA
- CUDA и удалённый GPU
- Что такое rCUDA
- Ограничения
- Возможные сценарии использования
- Краткая инструкция
- Тестовая конфигурация
- Получение rCUDA
- Установка CUDA
- Установка rCUDA
- Запуск демона rCUDA на сервере
- Настройка клиента
- Сборка и запуск
- Безопасность
Шпаргалка по установке CUDA, cuDNN, Tensorflow и PyTorch на Windows 10
В очередной раз после переустановки Windows осознал, что надо накатить драйвера, CUDA, cuDNN, Tensorflow/Keras для обучения нейронных сетей.
Каждый раз для меня это оказывается несложной, но времязатратной операцией: найти подходящую комбинацию Tensorflow/Keras, CUDA, cuDNN и Python несложно, но вспоминаю про эти зависимости только в тот момент, когда при импорте Tensorflow вижу, что видеокарта не обнаружена и начинаю поиск нужной страницы в документации Tensorflow.
В этот раз ситуация немного усложнилась. Помимо установки Tensorflow мне потребовалось установить PyTorch. Со своими зависимостями и поддерживаемыми версиями Python, CUDA и cuDNN.
По итогам нескольких часов экспериментов решил, что надо зафиксировать все полезные ссылки в одном посте для будущего меня.
Краткий алгоритм установки Tensorflow и PyTorch
Примечание: Установить Tensorflow и PyTorch можно в одном виртуальном окружении, но в статье этого алгоритма нет.
Подготовка к установке
- Определить какая версия Python поддерживается Tensorflow и PyTorch (на момент написания статьи мне не удалось установить PyTorch в виртуальном окружении с Python 3.9.5)
- Для выбранной версии Python найти подходящие версии Tensorflow и PyTorch
- Определить, какие версии CUDA поддерживают выбранные ранее версии Tensorflow и PyTorch
- Определить поддерживаемую версию cuDNN для Tensorflow – не все поддерживаемые CUDA версии cuDNN поддерживаются Tensorflow. Для PyTorch этой особенности не заметил
Установка CUDA и cuDNN
- Скачиваем подходящую версию CUDA и устанавливаем. Можно установить со всеми значениями по умолчанию
- Скачиваем cuDNN, подходящую для выбранной версии Tensorflow (п.1.2). Для скачивания cuDNN потребуется регистрация на сайте NVidia. “Установка” cuDNN заключается в распакове архива и заменой существующих файлов CUDA на файлы из архива
Устанавливаем Tensorflow
- Создаём виртуальное окружение для Tensorflow c выбранной версией Python. Назовём его, например, py38tf
- Переключаемся в окружение py38tf и устанавливаем поддерживаемую версию Tensorflow pip install tensorflow==x.x.x
- Проверяем поддержку GPU командой
Устанавливаем PyTorch
- Создаём виртуальное окружение для PyTorch c выбранной версией Python. Назовём его, например, py38torch
- Переключаемся в окружение py38torch и устанавливаем поддерживаемую версию PyTorch
- Проверяем поддержку GPU командой
В моём случае заработала комбинация:
- Python 3.8.8
- Драйвер NVidia 441.22
- CUDA 10.1
- cuDNN 7.6
- Tensorflow 2.3.0
- PyTorch 1.7.1+cu101
Tensorflow и PyTorch установлены в разных виртуальных окружениях.
Итого
Польза этой статьи будет понятна не скоро: систему переустанавливаю я не часто.
Если воспользуетесь этим алгоритмом и найдёте какие-то ошибки – пишите в комментарии
Источник
CUDA под Windows: советы в начале работы
Софт: Windows 7, 64bit; CUDA Toolkit 6.0; Microsoft Visual Studio 2008
Начал осваивать CUDA с чтения книги:
Сандерс Дж., Кэндрот Э. Технология CUDA в примерах. Введение в программирование графических процессоров. — М.: ДМК Пресс, 2013. — 232 с.: ил. — ISBN: 978-5-94074-504-4.
Что необходимо для работы с CUDA
Для работы с CUDA необходимо иметь:
- графический процессор (видеокарту), поддерживающий архитектуру CUDA;
- драйвер для этого устройства от NVIDIA;
- компилятор языка C;
- комплект средств разработки CUDA (CUDA Toolkit).
Пункты 1-3 у меня были, включая компилятор из набора Visual Studio 2008.
CUDA Toolkit можно скачать здесь. Вместе с ним поставляются многочисленные примеры, которые находятся в папке
C:\ProgramData\NVIDIA Corporation\CUDA Samples\v6.0
В папке 0_Simple\template находится заготовка для стандартного CUDA-проекта.
Как создавать проекты CUDA в Visual Studio и запускать примеры из книги
В VS при создании нового проекта выбираем тип NVIDIA/CUDA 6.0 и из шаблонов: CUDA Runtime 6.0.
После этого VS формирует заготовку проекта, содержащую единственный исходный файл kernel.cu . Он нам не нужен. Вместо него вставляем пример из книги:
Расширение файла .CU имеет значение! Только в таких файлах можно пользоваться CUDA-расширениями языка C++.
Чтобы настроить подсветку синтаксиса в файлах .CU как в C++, нужно в окне Tools -> Options -> Text Editor -> File Extension указать расширение .cu и в списке Editor: — Microsoft Visual C++. После перезапуска VS получим подсветку синтаксиса.
Сообщения об ошибках
В примере из Главы 4 «Вычисление фрактала Джулиа на GPU» (который, вообще говоря, называется множество Жюлиа)
Для исправления нужно добавить квалификатор __device__ в конструктор структуры:
Решение проблемы «Видеодрайвер nVidia перестал отвечать и был успешно восстановлен»
Такое сообщение появилось у меня при выполнении примера «Вычисление фрактала Джулиа на GPU» (глава 4). Драйвер видеокарты стоял самый новый, конфликтов с предыдущими версиями драйвера не обнаружилось. Видеокарта работала штатно и не была перегрета. Тем не менее сообщение появлялось.
Обзор возможных способов решения этой проблемы приведен здесь. В моем случае помог следующий рецепт.
Необходимо настроить в системном реестре два параметра:
- TdrLevel – управляет восстановлением. По умолчанию равен «3», что означает „TdrLevelRecover – Recover on timeout”, т. е. автоматическое восстановление по истечению времени задержки ( TdrDelay ). Значение «0» соответствует „TdrLevelOff – Detection disabled”, т. е. отключению детектирования ошибок драйвера.
- TdrDelay – время задержки (в секундах), иначе: время реагирования на бездействие драйвера. Значение по умолчанию равно «2». При отключении детектирования ошибок ( TdrLevel = 0 ) значение TdrDelay игнорируется.
Желательно не отключать проверку ошибок, а увеличить время задержки, установив его равным 3-м или более секундам. Значение подбирается экспериментально: можно начать с 10, и постепенно уменьшать время задержки.
Ключи TdrLevel и TdrDelay устанавливаются в редакторе реестра, в ветке HKLM\System\CurrentControlSet\Control\GraphicsDrivers . Возможно, что их придется создать. Ключи имеют тип REG_DWORD, не забудьте указать галочку «десятичная система счисления» при редактировании параметра.
Изменения в реестре вступят в силу после перезагрузки системы.
В результате получим:
Читайте также
Комментарии
Дмитрий Храмов
Компьютерное моделирование и все, что с ним связано: сбор данных, их анализ, разработка математических моделей, софт для моделирования, визуализации и оформления публикаций. Ну и за жизнь немного.
Источник
Параллельное программирование с CUDA. Часть 1: Введение
Еще одна статья о CUDA — зачем?
Содержание
Задержка vs пропускная способность
Первый вопрос, который должен задать каждый перед применением GPU для решения своих задач — а для каких целей хорош GPU, когда стоит его применять? Для ответа нужно определить 2 понятия:
Задержка (latency) — время, затрачиваемое на выполнение одной инструкции/операции.
Пропускная способность — количество инструкций/операций, выполняемых за единицу времени.
Простой пример: имеем легковой автомобиль со скоростью 90 км/ч и вместимостью 4 человека, и автобус со скоростью 60 км/ч и вместимостью 20 человек. Если за операцию принять перемещение 1 человека на 1 километр, то задержка легкового автомобиля — 3600/90=40с — за столько секунд 1 человек преодолеет расстояние в 1 километр, пропускная способность автомобиля — 4/40=0.1 операций/секунду; задержка автобуса — 3600/60=60с, пропускная способность автобуса — 20/60=0.3(3) операций/секунду.
Так вот, CPU — это автомобиль, GPU — автобус: он имеет большую задержку но также и большую пропускную способность. Если для вашей задачи задержка каждой конкретной операции не настолько важна как количество этих операций в секунду — стоит рассмотреть применение GPU.
Базовые понятия и термины CUDA
Итак, разберемся с терминологией CUDA:
- Устройство (device) — GPU. Выполняет роль «подчиненного» — делает только то, что ему говорит CPU.
- Хост (host) — CPU. Выполняет управляющую роль — запускает задачи на устройстве, выделяет память на устройстве, перемещает память на/с устройства. И да, использование CUDA предполагает, что как устройство так и хост имеют свою отдельную память.
- Ядро (kernel) — задача, запускаемая хостом на устройстве.
При использовании CUDA вы просто пишете код на своем любимом языке программирования (список поддерживаемых языков, не учитывая С и С++), после чего компилятор CUDA сгенерирует код отдельно для хоста и отдельно для устройства. Небольшая оговорка: код для устройства должен быть написан только на языке C с некоторыми ‘CUDA-расширениями’.
Основные этапы CUDA-программы
- Хост выделяет нужное количество памяти на устройстве.
- Хост копирует данные из своей памяти в память устройства.
- Хост стартует выполнение определенных ядер на устройстве.
- Устройство выполняет ядра.
- Хост копирует результаты из памяти устройства в свою память.
Естественно, для наибольшей эффективности использования GPU нужно чтобы соотношение времени, потраченного на работу ядер, к времени, потраченному на выделение памяти и перемещение данных, было как можно больше.
Рассмотрим более детально процесс написания кода для ядер и их запуска. Важный принцип — ядра пишутся как (практически) обычные последовательные программы — то-есть вы не увидите создания и запуска потоков в коде самих ядер. Вместо этого, для организации параллельных вычислений GPU запустит большое количество копий одного и того же ядра в разных потоках — а точнее, вы сами говорите сколько потоков запустить. И да, возвращаясь к вопросу эффективности использования GPU — чем больше потоков вы запускаете (при условии что все они будут выполнять полезную работу) — тем лучше.
Код для ядер отличается от обычного последовательного кода в таких моментах:
- Внутри ядер вы имеете возможность узнать «идентификатор» или, проще говоря, позицию потока, который сейчас выполняется — используя эту позицию мы добиваемся того, что одно и то же ядро будет работать с разными данными в зависимости от потока, в котором оно запущено. Кстати, такая организация параллельных вычислений называется SIMD (Single Instruction Multiple Data) — когда несколько процессоров выполняют одновременно одну и ту же операцию но на разных данных.
- В некоторых случаях в коде ядра необходимо использовать различные способы синхронизации.
Каким же образом мы задаем количество потоков, в которых будет запущено ядро? Поскольку GPU это все таки Graphics Processing Unit, то это, естественно, повлияло на модель CUDA, а именно на способ задания количества потоков:
- Сначала задаются размеры так называемой сетки (grid), в 3D координатах: grid_x, grid_y, grid_z. В результате, сетка будет состоять из grid_x*grid_y*grid_z блоков.
- Потом задаются размеры блока в 3D координатах: block_x, block_y, block_z. В результате, блок будет состоять из block_x*block_y*block_z потоков. Итого, имеем grid_x*grid_y*grid_z*block_x*block_y*block_z потоков. Важное замечание — максимальное количество потоков в одном блоке ограничено и зависит от модели GPU — типичны значения 512 (более старые модели) и 1024 (более новые модели).
- Внутри ядра доступны переменные threadIdx и blockIdx с полями x, y, z — они содержат 3D координаты потока в блоке и блока в сетке соответственно. Также доступны переменные blockDim и gridDim с теми же полями — размеры блока и сетки соответственно.
Как видите, данный способ запуска потоков действительно подходит для обработки 2D и 3D изображений: например, если нужно определенным образом обработать каждый пиксел 2D либо 3D изображения, то после выбора размеров блока (в зависимости от размеров картинки, способа обработки и модели GPU) размеры сетки выбираются такими, чтобы было покрыто все изображение, возможно, с избытком — если размеры изображения не делятся нацело на размеры блока.
Пишем первую программу на CUDA
Кстати, CUDA позволяет использовать C++ компилятор для host-кода — так что запросто можно написать обертки для автоматического освобождения памяти.
Итак, запускаем, измеряем (размер входного изображения — 10,109 × 4,542):
Конфигурация машины, на которой проводились тесты:
Количество блоков по x-координате теперь рассчитывается как numCols / (threadNum*elemsPerThread) + 1 вместо numCols / threadNum + 1. В остальном все осталось так же.
Запускаем:
Получили прирост по скорости в 2.76 раза (опять же, не учитывая время на операции с памятью) — для такой простой проблемы это довольно неплохо. Да-да, эта задача слишком простая — с ней достаточно хорошо справляется и CPU. Как видно из второго теста, простая реализация на GPU может даже проигрывать по скорости реализации на CPU.
На сегодня все, в следующей части рассмотрим аппаратное обеспечение GPU и основные шаблоны параллельной коммуникации.
Весь исходный код доступен на bitbucket.
Источник
CUDA и удалённый GPU
CUDA всем хороша, пока под рукой есть видеокарта от Nvidia. Но что делать, когда на любимом ноутбуке нет Nvidia видеокарты? Или нужно вести разработку в виртуальной машине?
Я постараюсь рассмотреть в этой статье такое решение, как фреймворк rCUDA (Remote CUDA), который поможет, когда Nvidia видеокарта есть, но установлена не в той машине, на которой предполагается запуск CUDA приложений. Тем, кому это интересно, добро пожаловать под кат.
rCUDA (Remote CUDA) — фреймворк, реализующий CUDA API, позволяющий использовать удалённую видеокарту. Находится в работоспособной бета-версии, доступен только под Linux. Основная цель rCUDA — полная совместимость с CUDA API, вам не нужно никак модифицировать свой код, достаточно задать специальные переменные среды.
Что такое rCUDA
rCUDA (Remote CUDA) — фреймворк, реализующий CUDA API, позволяющий использовать для CUDA вычислений видеокарту, расположенную на удалённой машине, не внося никаких изменений в ваш код. Разработан в политехническом университете Валенсии (rcuda-team).
Ограничения
На данный момент поддерживаются только GNU/Linux системы, однако разработчики обещают поддержку Windows в будущем. Текущая версия rCUDA, 18.03beta, совместима с CUDA 5-8, то есть CUDA 9 не поддерживается. Разработчиками заявлена полная совместимость с CUDA API, за исключением графики.
Возможные сценарии использования
Краткая инструкция
Тестовая конфигурация
Тестирование проводилось на следующей конфигурации:
Сервер:
Ubuntu 16.04, GeForce GTX 660
Клиент:
Виртуальная машина с Ubuntu 16.04 на ноутбуке без дискретной видеокарты.
Получение rCUDA
Cамый сложный этап. К сожалению, на данный момент единственный способ получить свой экземпляр этого фреймворка — заполнить соответствующую форму запроса на официальном сайте. Впрочем, разработчики обещают отвечать в течение 1-2 дней. В моём случае мне прислали дистрибутив в тот же день.
Установка CUDA
Для начала необходимо установить CUDA Toolkit на сервере и клиенте (даже если на клиенте нет nvidia видеокарты). Для этого можно скачать его с официального сайта или использовать репозиторий. Главное, использовать версию не выше 8. В данном примере используется установщик .run с оффициального сайта.
Важно! На клиенте следует отказаться от установки nvidia драйвера. По умолчанию CUDA Toolkit будет доступен по адресу /usr/local/cuda/. Установите CUDA Samples, они понадобятся.
Установка rCUDA
Распакуем полученный от разработчиков архив в нашу домашнюю директорию на сервере и на клиенте.
Проделать эти действия нужно как на сервере, так и на клиенте.
Запуск демона rCUDA на сервере
Замените на имя вашего пользователя. Используйте ./rCUDAd -iv, если хотите видеть подробный вывод.
Настройка клиента
Откроем на клиенте терминал, в котором в дальнейшем будем запускать CUDA код. На стороне клиента нам необходимо «подменить» стандартные библиотеки CUDA на библиотеки rCUDA, для чего добавим соответствующие пути в переменную среды LD_LIBRARY_PATH. Также нам необходимо указать количество серверов и их адреса (в моём примере он будет один).
Сборка и запуск
Попробуем собрать и запустить несколько примеров.
Пример 1
Начнём с простого, с deviceQuery — примера, который просто выведет нам параметры CUDA совместимого устройства, то есть в нашем случае удалённого GTX660.
Важно! Без EXTRA_NVCCFLAGS=—cudart=shared чуда не получится
Замените на путь, который вы указали для CUDA Samples при установке CUDA.
Запустим собранный пример:
Если вы всё сделали правильно, результат будет примерно таким:
Самое главное, что мы должны увидеть:
Device0 = GeForce GTX 660
Result = PASS
Отлично! Нам удалось собрать и запустить CUDA приложение на машине без дискретной видеокарты, использовав для этого видеокарту, установленную на удалённом сервере.
Важно! Если вывод приложения начинается со строк вида:
значит необходимо добавить на сервере и на клиенте в файл «/etc/security/limits.conf» следующие строки:
Таким образом, вы разрешите всем пользователям (*) неограниченное (unlimited) блокирование памяти (memlock). Еще лучше будет заменить * на нужного пользователя, а вместо unlimited подобрать менее жирные права.
Пример 2
Теперь попробуем что-то поинтереснее. Протестируем реализацию скалярного произведения векторов с использованием разделяемой памяти и синхронизации («Технология CUDA в примерах» Сандерс Дж. Кэндрот Э. 5.3.1).
В данном примере мы рассчитаем скалярное произведение двух векторов размерностью 33 * 1024, сравнивая ответ с результатом, полученным на CPU.
Сборка и запуск:
Такой результат говорит нам, что всё у нас хорошо:
Пример 3
Запустим еще один стандартный тест CUDA- matrixMulCUBLAS (перемножение матриц).
[Matrix Multiply CUBLAS] — Starting…
GPU Device 0: «GeForce GTX 660» with compute capability 3.0
MatrixA(640,480), MatrixB(480,320), MatrixC(640,320)
Computing result using CUBLAS. done.
Performance= 436.24 GFlop/s, Time= 0.451 msec, Size= 196608000 Ops
Computing result using host CPU. done.
Comparing CUBLAS Matrix Multiply with CPU results: PASS
NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.
Performance= 436.24 GFlop/s,
Comparing CUBLAS Matrix Multiply with CPU results: PASS
Безопасность
Я не нашёл в документации к rCUDA упоминания о каком-либо способе авторизации. Думаю, на данный момент самое простое, что можно сделать, это открыть доступ к нужному порту (8308) только с определённого адреса.
При помощи iptables это будет выглядеть так:
В остальном оставляю вопрос безопасности за рамками данного поста.
Источник