2011-12-22 7 views
2

У меня есть общие вопросы о параллелизме в коде CUDA или OpenCL на графическом процессоре. Я использую NVIDIA GTX 470.Параллельность в GPU - CUDA/OpenCL

Я кратко прочитал в руководстве по программированию Cuda, но не нашел соответствующих ответов, поэтому спрашивал здесь.

У меня есть функция верхнего уровня, которая вызывает ядро ​​CUDA (для того же ядра у меня есть версия OpenCL). Эта функция верхнего уровня называется 3 раза в «петле цикла» из моей основной функции, для 3 разных наборов данных (данные изображения R, G, B) , а фактический код также имеет обработку по всем пикселям изображения/так что он имеет 2 'для петель'.

Что я хочу знать, какой параллелизм используется здесь - параллелизм уровня задачи или параллелизм данных?

Так что я хочу понять, делает ли этот код CUDA и C несколько потоков для разных функций/функций в кодексе и коде верхнего уровня и выполняет их в параллельно и использует параллелизм задач. Если да, кто создает его, поскольку нет библиотеки потоков, явно включенной в код или связанной с ней.

ИЛИ

Это создает потоки/задачи для разных «для цикла» итераций, которые являются независимыми и, таким образом, достижением параллелизма данных. Если он делает такой параллелизм, использует ли он это, замечая, что разные для итераций цикла не имеют зависимостей и, следовательно, могут быть запланированы параллельно?

Потому что я не вижу каких-либо специальных конструкций/встроенных компиляторов (параллельных для циклов, как в openMP), которые сообщают компилятору/планировщику о планировании таких циклов/функций параллельно?

Любой материал для чтения поможет.

ответ

4

Параллелизм на графических процессорах - SIMT (однопроцессорные многопоточные потоки). Для ядер CUDA вы указываете сетку блоков, где каждый блок имеет N потоков. Библиотека CUDA выполняет весь трюк, а CUDA Compiler (nvcc) генерирует код GPU, который выполняет GPU. CUDA lib сообщает драйверу GPU и еще больше планировщик потоков на GPU, сколько потоков должно выполнять ядро ​​(количество блоков) x (количество потоков)). В вашем примере функция верхнего уровня (или функция хоста) выполняет только вызов ядра, который является асинхронным и возвращает emediatly. Нет библиотеки потоков, потому что nvcc создает вызовы для драйвера.

Вызов ядра образца выглядит следующим образом:

helloworld<<<BLOCKS, THREADS>>>(/* maybe some parameters */); 

OpenCL следует той же парадигме, но при компиляции Йора ядра (если они не прекомпилированы) во время выполнения. Укажите количество потоков для выполнения ядра, а lib - все остальное.

Лучший способ узнать CUDA (OpenCL) - посмотреть в CUDA Programming Guide (OpenCL Programming Guide) и посмотреть образцы в GPU Computing SDK.

2

Что я хочу знать, какой параллелизм используется здесь - параллелизм уровня задачи или параллелизм данных?

Преимущественно параллелизм данных, но есть и некоторые параллелизм задач.

В примере обработки изображений ядро ​​может выполнять обработку для одного выходного пикселя. Вы должны указывать OpenCL или CUDA для запуска столько потоков, сколько пикселей на выходном изображении. Затем он планирует эти потоки запускать на GPU/CPU, на которые вы нацеливаете.

Высоко данные параллельно. Ядро написано, чтобы сделать один рабочий элемент, и вы планируете миллионы из них.

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

2

Если вы запускаете несколько ядер, они не будут автоматически распараллеливаться (т. Е. Параллелизм задач с графическим процессором). Однако вызов ядра является асинхронным на стороне хоста, поэтому хост-код будет продолжать работать параллельно во время выполнения ядра.

Чтобы получить параллелизм задач, вы должны сделать это вручную - в Cuda понятие называется потоками и в командных очередях OpenCL. Без явного создания нескольких потоков/очередей и планирования каждого ядра в свою очередь они будут выполняться последовательно (есть функция OpenCL, позволяющая очереди работать не по порядку, но я не знаю, поддерживает ли какая-либо реализация.) Однако запуск параллельных ядер, вероятно, не принесет большой пользы, если каждый набор данных будет достаточно большим, чтобы использовать все ядра графического процессора.

Если у вас есть фактические для циклов в ваших ядрах, они сами по себе не будут распараллеливаться, параллелизм исходит из указания размера сетки, из-за чего ядро ​​будет вызываться параллельно для каждого элемента в этой сетке (так что если у вас есть петли внутри вашего ядра, они будут выполнены полностью по каждой теме). Другими словами, вы должны указать размер сетки при вызове ядра, а внутри ядра использовать threadIdx/blockIdx (Cuda) или getGlobalId() (OpenCL), чтобы определить, какой элемент данных обрабатывать в этом конкретном потоке.

Полезная книга для изучения OpenCL - это OpenCL Programming Guide, но также стоит посмотреть на OpenCL spec.

Смежные вопросы