Как проверить работает ли cuda
Перейти к содержимому

Как проверить работает ли cuda

  • автор:

CUDA: Как работает GPU

Внутренняя модель nVidia GPU – ключевой момент в понимании GPGPU с использованием CUDA. В этот раз я постараюсь наиболее детально рассказать о программном устройстве GPUs. Я расскажу о ключевых моментах компилятора CUDA, интерфейсе CUDA runtime API, ну, и в заключение, приведу пример использования CUDA для несложных математических вычислений.

Вычислительная модель GPU:

Рассмотрим вычислительную модель GPU более подробно.

    Верхний уровень ядра GPU состоит из блоков, которые группируются в сетку или грид (grid) размерностью N1 * N2 * N3. Это можно изобразить следующим образом:

    Рис. 1. Вычислительное устройство GPU.

Размерность сетки блоков можно узнать с помощь функции cudaGetDeviceProperties, в полученной структуре за это отвечает поле maxGridSize. К примеру, на моей GeForce 9600M GS размерность сетки блоков: 65535*65535*1, то есть сетка блоков у меня двумерная (полученные данные удовлетворяют Compute Capability v.1.1).

  • Любой блок в свою очередь состоит из нитей (threads), которые являются непосредственными исполнителями вычислений. Нити в блоке сформированы в виде трехмерного массива (рис. 2), размерность которого так же можно узнать с помощью функции cudaGetDeviceProperties, за это отвечает поле maxThreadsDim.
  • Рис. 2. Устройство блока GPU.

    При использовании GPU вы можете задействовать грид необходимого размера и сконфигурировать блоки под нужды вашей задачи.

    CUDA и язык C:

    1. Спецификаторы функций, которые показывают, как и откуда буду выполняться функции.
    2. Спецификаторы переменных, которые служат для указания типа используемой памяти GPU.
    3. Спецификаторы запуска ядра GPU.
    4. Встроенные переменные для идентификации нитей, блоков и др. параметров при исполнении кода в ядре GPU .
    5. Дополнительные типы переменных.
    • __host__ — выполнятся на CPU, вызывается с CPU (в принципе его можно и не указывать).
    • __global__ — выполняется на GPU, вызывается с CPU.
    • __device__ — выполняется на GPU, вызывается с GPU.
    • gridSize – размерность сетки блоков (dim3), выделенную для расчетов,
    • blockSize – размер блока (dim3), выделенного для расчетов,
    • sharedMemSize – размер дополнительной памяти, выделяемой при запуске ядра,
    • cudaStream – переменная cudaStream_t, задающая поток, в котором будет произведен вызов.
    • gridDim – размерность грида, имеет тип dim3. Позволяет узнать размер гридa, выделенного при текущем вызове ядра.
    • blockDim – размерность блока, так же имеет тип dim3. Позволяет узнать размер блока, выделенного при текущем вызове ядра.
    • blockIdx – индекс текущего блока в вычислении на GPU, имеет тип uint3.
    • threadIdx – индекс текущей нити в вычислении на GPU, имеет тип uint3.
    • warpSize – размер warp’а, имеет тип int (сам еще не пробовал использовать).

    Дополнительные типы переменных и их спецификаторы будут рассмотрены непосредственно в примерах работы с памятью.

    CUDA host API:

    Перед тем, как приступить к непосредственному использованию CUDA для вычислений, необходимо ознакомиться с так называемым CUDA host API, который является связующим звеном между CPU и GPU. CUDA host API в свою очередь можно разделить на низкоуровневое API под названием CUDA driver API, который предоставляет доступ к драйверу пользовательского режима CUDA, и высокоуровневое API – CUDA runtime API. В своих примерах я буду использовать CUDA runtime API.

    • Device Management – включает функции для общего управления GPU (получение инфор-мации о возможностях GPU, переключение между GPU при работе SLI-режиме и т.д.).
    • Thread Management – управление нитями.
    • Stream Management – управление потоками.
    • Event Management – функция создания и управления event’ами.
    • Execution Control – функции запуска и исполнения ядра CUDA.
    • Memory Management – функции управлению памятью GPU.
    • Texture Reference Manager – работа с объектами текстур через CUDA.
    • OpenGL Interoperability – функции по взаимодействию с OpenGL API.
    • Direct3D 9 Interoperability – функции по взаимодействию с Direct3D 9 API.
    • Direct3D 10 Interoperability – функции по взаимодействию с Direct3D 10 API.
    • Error Handling – функции обработки ошибок.

    Понимаем работу GPU:

    Как было сказано, нить – непосредственный исполнитель вычислений. Каким же тогда образом происходит распараллеливание вычислений между нитями? Рассмотрим работу отдельно взятого блока.

    Задача. Требуется вычислить сумму двух векторов размерностью N элементов.

    Нам известна максимальные размеры нашего блока: 512*512*64 нитей. Так как вектор у нас одномерный, то пока ограничимся использованием x-измерения нашего блока, то есть задействуем только одну полосу нитей из блока (рис. 3).

    Рис. 3. Наша полоса нитей из используемого блока.

    1. Получить данные для расчетов.
    2. Скопировать эти данные в GPU память.
    3. Произвести вычисление в GPU через функцию ядра.
    4. Скопировать вычисленные данные из GPU памяти в ОЗУ.
    5. Посмотреть результаты.
    6. Высвободить используемые ресурсы.

    Первым делом напишем функцию ядра, которая и будет осуществлять сложение векторов:

    // Функция сложения двух векторов
    __global__ void addVector( float * left, float * right, float * result)
    //Получаем id текущей нити.
    int idx = threadIdx.x;

    //Расчитываем результат.
    result[idx] = left[idx] + right[idx];
    >

    * This source code was highlighted with Source Code Highlighter .

    Таким образом, распараллеливание будет выполнено автоматически при запуске ядра. В этой функции так же используется встроенная переменная threadIdx и её поле x, которая позволяет задать соответствие между расчетом элемента вектора и нитью в блоке. Делаем расчет каждого элемента вектора в отдельной нити.

    Пишем код, которые отвечает за 1 и 2 пункт в программе:

    #define SIZE 512
    __host__ int main()
    //Выделяем память под вектора
    float * vec1 = new float [SIZE];
    float * vec2 = new float [SIZE];
    float * vec3 = new float [SIZE];

    //Инициализируем значения векторов
    for ( int i = 0; i < SIZE; i++)
    vec1[i] = i;
    vec2[i] = i;
    >

    //Указатели на память видеокарте
    float * devVec1;
    float * devVec2;
    float * devVec3;

    //Копируем данные в память видеокарты
    cudaMemcpy(devVec1, vec1, sizeof ( float ) * SIZE, cudaMemcpyHostToDevice);
    cudaMemcpy(devVec2, vec2, sizeof ( float ) * SIZE, cudaMemcpyHostToDevice);

    >

    * This source code was highlighted with Source Code Highlighter .

    1. devPtr – указатель, в который записывается адрес выделенной памяти,
    2. count – размер выделяемой памяти в байтах.
    1. cudaSuccess – при удачном выделении памяти
    2. cudaErrorMemoryAllocation – при ошибке выделения памяти
    1. dst – указатель, содержащий адрес места-назначения копирования,
    2. src – указатель, содержащий адрес источника копирования,
    3. count – размер копируемого ресурса в байтах,
    4. cudaMemcpyKind – перечисление, указывающее направление копирования (может быть cudaMemcpyHostToDevice, cudaMemcpyDeviceToHost, cudaMemcpyHostToHost, cudaMemcpyDeviceToDevice).
    1. cudaSuccess – при удачном копировании
    2. cudaErrorInvalidValue – неверные параметры аргумента (например, размер копирования отрицателен)
    3. cudaErrorInvalidDevicePointer – неверный указатель памяти в видеокарте
    4. cudaErrorInvalidMemcpyDirection – неверное направление (например, перепутан источник и место-назначение копирования)


    dim3 gridSize = dim3(1, 1, 1); //Размер используемого грида
    dim3 blockSize = dim3(SIZE, 1, 1); //Размер используемого блока

    //Выполняем вызов функции ядра
    addVector>>(devVec1, devVec2, devVec3);

    * This source code was highlighted with Source Code Highlighter .

    В нашем случае определять размер грида и блока необязательно, так как используем всего один блок и одно измерение в блоке, поэтому код выше можно записать:

    * This source code was highlighted with Source Code Highlighter .

    Теперь нам остаеться скопировать результат расчета из видеопамяти в память хоста. Но у функций ядра при этом есть особенность – асинхронное исполнение, то есть, если после вызова ядра начал работать следующий участок кода, то это ещё не значит, что GPU выполнил расчеты. Для завершения работы заданной функции ядра необходимо использовать средства синхронизации, например event’ы. Поэтому, перед копированием результатов на хост выполняем синхронизацию нитей GPU через event.

    Код после вызова ядра:

    //Выполняем вызов функции ядра
    addVector>>(devVec1, devVec2, devVec3);

    //Хендл event’а
    cudaEvent_t syncEvent;

    cudaEventCreate(&syncEvent); //Создаем event
    cudaEventRecord(syncEvent, 0); //Записываем event
    cudaEventSynchronize(syncEvent); //Синхронизируем event

    //Только теперь получаем результат расчета
    cudaMemcpy(vec3, devVec3, sizeof ( float ) * SIZE, cudaMemcpyDeviceToHost);

    * This source code was highlighted with Source Code Highlighter .

    Рассмотрим более подробно функции из Event Managment API.

    1. *event – указатель для записи хендла event’а.
    1. cudaSuccess – в случае успеха
    2. cudaErrorInitializationError – ошибка инициализации
    3. cudaErrorPriorLaunchFailure – ошибка при предыдущем асинхронном запуске функции
    4. cudaErrorInvalidValue – неверное значение
    5. cudaErrorMemoryAllocation – ошибка выделения памяти
    1. event – хендл хаписываемого event’а,
    2. stream – номер потока, в котором записываем (в нашем случае это основной нулевой по-ток).
    1. cudaSuccess – в случае успеха
    2. cudaErrorInvalidValue – неверное значение
    3. cudaErrorInitializationError – ошибка инициализации
    4. cudaErrorPriorLaunchFailure – ошибка при предыдущем асинхронном запуске функции
    5. cudaErrorInvalidResourceHandle – неверный хендл event’а
    1. event – хендл event’а, прохождение которого ожидается.
    1. cudaSuccess – в случае успеха
    2. cudaErrorInitializationError – ошибка инициализации
    3. cudaErrorPriorLaunchFailure – ошибка при предыдущем асинхронном запуске функции
    4. cudaErrorInvalidValue – неверное значение
    5. cudaErrorInvalidResourceHandle – неверный хендл event’а

    Рис. 4. Синхронизация работы основоной и GPU прграмм.

    На рисунке 4 блок «Ожидание прохождения Event’а» и есть вызов функции cudaEventSynchronize.

    Ну и в заключении выводим результат на экран и чистим выделенные ресурсы.

    cudaFree(devVec1);
    cudaFree(devVec2);
    cudaFree(devVec3);

    delete[] vec1; vec1 = 0;
    delete[] vec2; vec2 = 0;
    delete[] vec3; vec3 = 0;

    * This source code was highlighted with Source Code Highlighter .

    Думаю, что описывать функции высвобождения ресурсов нет необходимости. Разве что, можно напомнить, что они так же возвращают значения cudaError_t, если есть необходимость проверки их работы.

    Заключение

    Надеюсь, что этот материал поможет вам понять, как функционирует GPU. Я описал самые главные моменты, которые необходимо знать для работы с CUDA. Попробуйте сами написать сложение двух матриц, но не забывайте об аппаратных ограничениях видеокарты.

    P.S.: Получилось не очень кратко. Надеюсь, что не утомил. Если нужен весь исходный код, то могу выслать на почту.
    P.S.S: Задавайте вопросы.

    TensorFlow не видит Cuda

    Пользуюсь JupyterNotebook из дистрибутива Anaconda. ОС — Windows 11. CUDA v11. CUDNN v8.7. Команда nvcc -V в PowerShell работает, выводит версию CUDA.

    Отслеживать
    задан 30 янв в 15:01
    11 3 3 бронзовых знака

    А посмотрите что внутри ноутбука выдаст !set , правильный ли там PATH ? И !python -V посмотрите, та ли версия питона запускается. В общем, посмотрите окружение из самого юпитер ноутбука, всё ли там нормально.

    31 янв в 6:54

    1 ответ 1

    Сортировка: Сброс на вариант по умолчанию

    Долго мучился с похожей проблемой. Переустановил всё что можно и CUDA, и Python, и библиотеки, и разные версии всего, что только можно. В итоге на одном сайте, нашёл информацию как проверить версию установленного драйвера CUDA https://russianblogs.com/article/8204984484/. Если кратко, то в трее двойным щелчком открываете настройки Nvidia

    Скриншот трея

    Затем в левом нижнем углу нажимаем информация о системе

    Панель Nvidia

    [

    Переходим на вкладку Компоненты и смотрим версию драйвера CUDA

    Версия драйвера CUDA

    Поскольку я не так давно обновился, то отображается стоит 12.0. И видимо поэтому при установке более ранней CUDA tensorflow не запускался. После этого скачал и установил CUDA Toolkit 12.0 и tensorflow начал нормально видеть GPU.

    Вопросы с меткой [cuda]

    CUDA – это архитектура параллельных вычислений от NVIDIA, позволяющая существенно увеличить вычислительную производительность благодаря использованию GPU.

    121 вопрос
    Конкурсные
    Неотвеченные

    • Конкурсные 0
    • Неотвеченные
    • Цитируемые
    • Рейтинг
    • Неотвеченные (мои метки)

    16 показов

    Не работает cuda toolkit и cmake

    Устанавил cuda toolkit и запустил файл для работы с pytorch c++ и возникает ошибка: CMake Error at C:/Program Files/CMake/share/cmake-3.28/Modules/CMakeDetermineCompilerId.cmake:780 (message).

    задан 23 окт в 10:15
    59 показов

    Таблица ранжирования видеокарт Nvidia по вычислительной производительности CUDA

    Прошу не минусить за вопрос, который «можно погуглить». Гуглил уже 1.5 часа. Суть вопроса. Некоторые пакеты распознания текстов и т.п. требуют видеокарту определенного поколения или уровня .

    задан 4 сен в 9:01
    18 показов

    как установить cuda 11.1 и nvidia driver 450

    ставлю cuda 11.1 он автоматом подтягивает драйвер 455 версии, как использовать cuda v 11.1 и nvidia_driver_450?

    задан 23 авг в 6:42

    Запуск программы на пайтон через GPU

    Я запускаю программу, работающую на основе библиотеки easyocr, при каждом запуске программа выдает в консоль информацию: Neither CUDA nor MPS are available — defaulting to CPU. Примечание: Этот .

    задан 26 июн в 23:04
    208 показов

    Cuda работает, но GPU не производит вычислений. Pytorch-Cuda (Jupyter)

    У меня установлена Cuda 11.8 в соответствии с версиями библиотек. torch.cuda.is_available() дает True и соответственно всего распознает одно устройство GPU, но при запуске нейронной сети CNN в .

    задан 4 мая в 20:42

    torch.cuda.is_available() = False JupyterNotebook

    У меня видеокарта nvidia 1060. Стоит cuda 12.1. В Python torch.cuda.is_available() == True в JupyterNotebook torch.cuda.is_available() == False. Естественно ставил с сайта pytorch.org и выбирал: .

    задан 3 мая в 10:03

    GPU && PyTorch: на что влияет разрядность шины данных?

    На что влияет разрядность шины данных? У RTX 4090 она 384 бит. У Quadro A6000 она то же 384, и стоит она в 3 раза дороже наверное потому что у нее больше памяти. А вот у Tesla A100 она составляет 5120 .

    задан 13 апр в 17:45

    CUDA простая задача

    Задача такая: даны три массива длины n, R[], G[], B[]. Надо найти количество таких индексов i, что R[i] * G[i] * B[i]
    задан 2 апр в 9:53

    Передача динамического двумерного массива в kernal и на host. cuda

    есть код, который должен передавать матрицы в ядро, складывать их и возвращать обратно на хост матрицу с ответом(ответ сложения матриц записывается в третью матрицу). Передать на устройство и обратно .

    задан 23 мар в 16:18
    870 показов

    pytorch не видит cuda

    Я совсем новичок в этой теме и начал читать книгу. Тк на моем пк есть GPU, я захотел использовать cuda для работы с pytorch, но столкнулся с проблемой, что не могу его верно установить. >>> .

    задан 3 фев в 15:25
    660 показов

    TensorFlow не видит Cuda

    Установил CUDA toolkit и CUDNN, добавил в PATH, но данная функция все равно возвращает False. import tensorflow as tf print(tf.test.is_built_with_cuda()) Пользуюсь JupyterNotebook из дистрибутива .

    задан 30 янв в 15:01
    56 показов

    Не работает рабочий стол после установки CUDA

    Я установил CUDA командой sudo apt-get install nvidia-cuda-toolkit но после перезапуска не работает рабочий стол. Сначала не запускался а после попросило ввойти. Рабочий стол загрузился но ничего не .

    задан 21 дек 2022 в 18:33
    47 показов

    Visual Studio проект на CUDA runtime: символы юникода в пути сборки

    Я создал проект на CUDA через visual studio. Располагается он по пути, содержащем русские символы. При сборке проекта, возникает ошибка: Error C1083 Cannot open compiler generated file: ‘C:\Users\.

    задан 14 дек 2022 в 16:13
    15 показов

    Использование MyCaffe

    В описании указано, что MyCaffe требует установленного инструментария CUDA 11.8.0 (или 11.7.1) и набор библиотек cuDnn 8.7.0 (или 8.5.0 соответственно). Но CUDA предназначен, как я понимаю, для .

    задан 7 дек 2022 в 14:47

    Как установить и использовать TensorFlow и Keras без CUDA?

    Пытаюсь установить TensorFlow и Keras пытаюсь импортировать(import tensorflow) и получаю следующую ошибку: 2022-11-08 22:32:36.638616: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] .

    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, за исключением графики.

    Возможные сценарии использования

    1. Запуск CUDA приложений в виртуальной машине тогда, когда проброс видеокарты неудобен или невозможен, например, когда видеокарта занята хостом, или когда виртуальных машин больше одной.
    2. Ноутбук без дискретной видеокарты.
    3. Желание использовать несколько видеокарт (кластеризация). Теоретически, можно использовать все имеющиеся в команде видеокарты, в том числе совместо.

    Краткая инструкция

    Тестовая конфигурация

    Тестирование проводилось на следующей конфигурации:

    Сервер:
    Ubuntu 16.04, GeForce GTX 660

    Клиент:
    Виртуальная машина с Ubuntu 16.04 на ноутбуке без дискретной видеокарты.

    Получение rCUDA

    Cамый сложный этап. К сожалению, на данный момент единственный способ получить свой экземпляр этого фреймворка — заполнить соответствующую форму запроса на официальном сайте. Впрочем, разработчики обещают отвечать в течение 1-2 дней. В моём случае мне прислали дистрибутив в тот же день.

    Установка CUDA

    Для начала необходимо установить CUDA Toolkit на сервере и клиенте (даже если на клиенте нет nvidia видеокарты). Для этого можно скачать его с официального сайта или использовать репозиторий. Главное, использовать версию не выше 8. В данном примере используется установщик .run с оффициального сайта.

    chmod +x cuda_8.0.61_375.26_linux.run ./cuda_8.0.61_375.26_linux.run

    Важно! На клиенте следует отказаться от установки nvidia драйвера. По умолчанию CUDA Toolkit будет доступен по адресу /usr/local/cuda/. Установите CUDA Samples, они понадобятся.

    Установка rCUDA

    Распакуем полученный от разработчиков архив в нашу домашнюю директорию на сервере и на клиенте.

    tar -xvf rCUDA*.tgz -C ~/ mv ~/rCUDA* ~/rCUDA

    Проделать эти действия нужно как на сервере, так и на клиенте.

    Запуск демона rCUDA на сервере
    export PATH=$PATH/usr/local/cuda/bin export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64:/home//rCUDA/lib/cudnn cd ~/rCUDA/bin ./rCUDAd 

    Замените < XXX>на имя вашего пользователя. Используйте ./rCUDAd -iv, если хотите видеть подробный вывод.

    Настройка клиента

    Откроем на клиенте терминал, в котором в дальнейшем будем запускать CUDA код. На стороне клиента нам необходимо «подменить» стандартные библиотеки CUDA на библиотеки rCUDA, для чего добавим соответствующие пути в переменную среды LD_LIBRARY_PATH. Также нам необходимо указать количество серверов и их адреса (в моём примере он будет один).

    export PATH=$PATH/usr/local/cuda/bin export LD_LIBRARY_PATH=/home//rCUDA/lib/:$LD_LIBRARY_PATH export RCUDA_DEVICE_COUNT=1 # укажем количество видеокарт (серверов), их может быть несколько export RCUDA_DEVICE_0=:0 # укажем адрес первого сервера
    Сборка и запуск

    Попробуем собрать и запустить несколько примеров.

    Пример 1

    Начнём с простого, с deviceQuery — примера, который просто выведет нам параметры CUDA совместимого устройства, то есть в нашем случае удалённого GTX660.

    cd /NVIDIA_CUDA-8.0_Samples/1_Utilities/deviceQuery make EXTRA_NVCCFLAGS=--cudart=shared

    Важно! Без EXTRA_NVCCFLAGS=—cudart=shared чуда не получится
    Замените на путь, который вы указали для CUDA Samples при установке CUDA.

    Запустим собранный пример:

    ./deviceQuery

    Если вы всё сделали правильно, результат будет примерно таким:

    Результат

    ./deviceQuery Starting. CUDA Device Query (Runtime API) version (CUDART static linking) Detected 1 CUDA Capable device(s) Device 0: "GeForce GTX 660" CUDA Driver Version / Runtime Version 9.0 / 8.0 CUDA Capability Major/Minor version number: 3.0 Total amount of global memory: 1994 MBytes (2090991616 bytes) ( 5) Multiprocessors, (192) CUDA Cores/MP: 960 CUDA Cores GPU Max Clock rate: 1072 MHz (1.07 GHz) Memory Clock rate: 3004 Mhz Memory Bus Width: 192-bit L2 Cache Size: 393216 bytes Maximum Texture Dimension Size (x,y,z) 1D=(65536), 2D=(65536, 65536), 3D=(4096, 4096, 4096) Maximum Layered 1D Texture Size, (num) layers 1D=(16384), 2048 layers Maximum Layered 2D Texture Size, (num) layers 2D=(16384, 16384), 2048 layers Total amount of constant memory: 65536 bytes Total amount of shared memory per block: 49152 bytes Total number of registers available per block: 65536 Warp size: 32 Maximum number of threads per multiprocessor: 2048 Maximum number of threads per block: 1024 Max dimension size of a thread block (x,y,z): (1024, 1024, 64) Max dimension size of a grid size (x,y,z): (2147483647, 65535, 65535) Maximum memory pitch: 2147483647 bytes Texture alignment: 512 bytes Concurrent copy and kernel execution: Yes with 1 copy engine(s) Run time limit on kernels: Yes Integrated GPU sharing Host Memory: No Support host page-locked memory mapping: Yes Alignment requirement for Surfaces: Yes Device has ECC support: Disabled Device supports Unified Addressing (UVA): Yes Device PCI Domain ID / Bus ID / location ID: 0 / 1 / 0 Compute Mode: < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 9.0, CUDA Runtime Version = 8.0, NumDevs = 1, Device0 = GeForce GTX 660 Result = PASS

    Самое главное, что мы должны увидеть:

    Device0 = GeForce GTX 660
    Result = PASS

    Отлично! Нам удалось собрать и запустить CUDA приложение на машине без дискретной видеокарты, использовав для этого видеокарту, установленную на удалённом сервере.

    Важно! Если вывод приложения начинается со строк вида:

    mlock error: Cannot allocate memory rCUDA warning: 1007.461 mlock error: Cannot allocate memory 

    значит необходимо добавить на сервере и на клиенте в файл «/etc/security/limits.conf» следующие строки:

    * hard memlock unlimited * soft memlock unlimited 

    Таким образом, вы разрешите всем пользователям (*) неограниченное (unlimited) блокирование памяти (memlock). Еще лучше будет заменить * на нужного пользователя, а вместо unlimited подобрать менее жирные права.

    Пример 2

    Теперь попробуем что-то поинтереснее. Протестируем реализацию скалярного произведения векторов с использованием разделяемой памяти и синхронизации («Технология CUDA в примерах» Сандерс Дж. Кэндрот Э. 5.3.1).

    В данном примере мы рассчитаем скалярное произведение двух векторов размерностью 33 * 1024, сравнивая ответ с результатом, полученным на CPU.

    dotProd.cu

    #include #define imin(a,b) (a // set the cache values cache[cacheIndex] = temp; // synchronize threads in this block __syncthreads(); // for reductions, threadsPerBlock must be a power of 2 // because of the following code int i = blockDim.x/2; while (i != 0) < if (cacheIndex < i) cache[cacheIndex] += cache[cacheIndex + i]; __syncthreads(); i /= 2; >if (cacheIndex == 0) c[blockIdx.x] = cache[0]; > int main (void) < float *a, *b, c, *partial_c; float *dev_a, *dev_b, *dev_partial_c; // allocate memory on the cpu side a = (float*)malloc(N*sizeof(float)); b = (float*)malloc(N*sizeof(float)); partial_c = (float*)malloc(blocksPerGrid*sizeof(float)); // allocate the memory on the gpu cudaMalloc((void**)&dev_a, N*sizeof(float)); cudaMalloc((void**)&dev_b, N*sizeof(float)); cudaMalloc((void**)&dev_partial_c, blocksPerGrid*sizeof(float)); // fill in the host memory with data for(int i=0; i// copy the arrays 'a' and 'b' to the gpu cudaMemcpy(dev_a, a, N*sizeof(float), cudaMemcpyHostToDevice); cudaMemcpy(dev_b, b, N*sizeof(float), cudaMemcpyHostToDevice); dot>>(dev_a, dev_b, dev_partial_c); // copy the array 'c' back from the gpu to the cpu cudaMemcpy(partial_c,dev_partial_c, blocksPerGrid*sizeof(float), cudaMemcpyDeviceToHost); // finish up on the cpu side c = 0; for(int i=0; i #define sum_squares(x) (x*(x+1)*(2*x+1)/6) printf("GPU - %.6g \nCPU - %.6g\n", c, 2*sum_squares((float)(N-1))); // free memory on the gpu side cudaFree(dev_a); cudaFree(dev_b); cudaFree(dev_partial_c); // free memory on the cpu side free(a); free(b); free(partial_c); > 

    Сборка и запуск:

    /usr/local/cuda/bin/nvcc --cudart=shared dotProd.cu -o dotProd ./dotProd

    Такой результат говорит нам, что всё у нас хорошо:

    GPU — 2.57236e+13
    CPU — 2.57236e+13

    Пример 3

    Запустим еще один стандартный тест CUDA- matrixMulCUBLAS (перемножение матриц).

    cd < YYY>/NVIDIA_CUDA-8.0_Samples/0_Simple/matrixMulCUBLAS make EXTRA_NVCCFLAGS=--cudart=shared ./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 это будет выглядеть так:

    iptables -A INPUT -m state --state NEW -p tcp -s --dport 8308 -j ACCEPT

    В остальном оставляю вопрос безопасности за рамками данного поста.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *