Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие_CUDA.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
5.04 Mб
Скачать
      1. Теоретическая часть

Разработка приложения с использованием архитектуры CUDA ничем не отличается от создания компьютерной программы на любом языке программирования. Важно лишь разбираться в принципах организации параллельных вычислений.

Любое CUDA-приложение, должно включать следующие этапы:

  1. Выбор и инициализацию видеокарты;

  2. Выделение массивов данных в памяти GPU;

  3. Загрузки данных на устройство;

  4. Вычисление в GPU через функцию ядра;

  5. Копирование вычисленных данных из GPU памяти в ОЗУ;

  6. Освобождение выделенных ресурсов GPU.

Инициализация устройства.

Для управления устройствами, поддерживающими технологию CUDA, можно использовать функцию cudaGetDeviceCount, возвращающую количество устройств и функцию cudaGetDeviceProperties, описывающую свойства каждого устройства.

Функция cudaSetDevice используется для выбора устройства: cudaSetDevice(device). Устройство должно быть выбрано раньше любого вызова __global__ функции, если этого не произошло, по умолчанию ставится устройство с номером 0. Если требуется работать с несколькими устройствами, то необходимо использовать несколько потоков в программе.

Выделение памяти на gpu

Одним из способов выделения памяти в CUDA является использование функций cudaMalloc и cudaMallocPitch.

Функция cudaMalloc имеет следующий прототип:

cudaError_t cudaMalloc(void** devPtr, size_t count); где devPtr – указатель, в который записывается адрес выделенной памяти;

count – размер выделяемой памяти в байтах.

Возвращает:

cudaSuccess – при удачном выделении памяти;

cudaErrorMemoryAllocation – при ошибке выделения памяти.

Для выделения памяти под двухмерные массивы более подходящей является функция cudaMallocPitch, которая осуществляет выравнивание строк массива для более эффективного доступа к памяти. При этом в параметре pitch возвращается размер строки в байтах:

cudaError_t cudaMallocPitch (void ** devPtr, size_t * pitch,size_t width, size_t height)

Для выделения памяти на центральном процессоре помимо стандартных функций операционной системы можно воспользоваться функцией cudaMallocHost.

cudaError_t cudaMallocHost(void** hostPtr, size_t count);

Функция выделяет память на CPU в режиме блокировки от подкачки. Данный способ выделения памяти сильно ускоряет обмен данными с GPU. Однако частое использование данной функции может привести к падению производительности центрального процессора.

Пересылка данных между cpu и gpu.

Для взаимодействия CPU и GPU используется глобальная память, размеры которой могут варьироваться от нескольких сотен мегабайт до нескольких гигабайт. Скорость передачи данных с хоста на устройство ограничивается пропускной способностью шины PCI Express.

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

Для копирования данных между хостом и устройством используются функции cudaMemcpy и cudaMemcpyAsync, которые имеют следующий прототип:

cudaError_t cudaMemcpy( void * dst, const void * src, size_t count, enum cudaMemcpyKind kind );

cudaError_t cudaMemcpyAsync ( void * dst, const void * src, size_t count, enum cudaMemcpyKind kind, cudaStream_t stream );

где dst – указатель, содержащий адрес места назначения копирования;

src – указатель, содержащий адрес источника копирования;

count – размер копируемого ресурса в байтах;

kind – направление копирования может принимать значения:

  • cudaMemcpyHostToDevice – c хоста на устройство,

  • cudaMemcpyDeviceToHost – с устройства на хост,

  • cudaMemcpyDeviceToDevice – с устройства на устройство,

  • cudaMemcpyHostToHost – с хоста на хост.

stream – описение потока, в котором запускается функция.

Возвращает:

cudaSuccess – при удачном копировании,

cudaErrorInvalidValue – неверный указатель памяти в видеокарте,

cudaErrorInvalidMemcpyDirection – неверное направление.

Функция cudaMemcpyAsync ассинхронная, т.е. управление в основную программу хоста возвратится до реального ее выполнения. Для завершения работы функции необходимо использовать средства синхронизации, например функцию cudaThreadSynchronize().

Функция cudaMemcpyAsync работает только с памятью выделенной с помощью функции cudaMallocHost.

Для очистки выделенных ресурсов служат следующие функции:

cudaFreeHost (void * ptr) – очищает память с адреса, на который указывает ptr.

cudaFree (void *devPtr) – очищает память с адреса, указанного в devPtr.