2012-02-16 2 views
6

Использование разных потоков для ядер CUDA делает возможным одновременное выполнение ядра. Поэтому ядра n на n потоках теоретически могут выполняться одновременно, если они подходят к оборудованию, верно?Совместное выполнение ядра CUDA с несколькими ядрами на поток

Теперь я столкнулся со следующей проблемой: Не существует n различных ядер, но n*m, где ядра m необходимо заказывать по порядку. Например n=2 и m=3 приведет к следующей схеме исполнения с потоками:

Stream 1: <<<Kernel 0.1>>> <<<Kernel 1.1>>> <<<Kernel 2.1>>> 
Stream 2: <<<Kernel 0.2>>> <<<Kernel 1.2>>> <<<Kernel 2.2>>> 

Моя наивным предположение, что ядра X.0 и Y.1 должны выполняться одновременно (с теоретической точки зрения) или, по крайней мере, не последовательно (с практической точки зрения). Но мои измерения показывают мне, что это не так, и кажется, что выполняется последовательное выполнение (то есть K0.0, K1.0, K2.0, K0.1, K1.1, K2.1). Ядра сами очень малы, поэтому одновременное выполнение не должно быть проблемой.

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

Хорошо, подходит к делу: что было бы подходящим (или хотя бы разным) подходом к решению этой ситуации?

Редактировать: Измерения проводятся с использованием событий CUDA. Я измерил время, необходимое для полного решения вычислений, т.е. е. GPU должен вычислить все ядра n * m. Предполагается следующее: при полностью параллельном выполнении ядра время выполнения примерно (желательно) 1/n времени, необходимого для выполнения всех ядер в порядке, в результате чего должно быть возможно одновременное выполнение двух или более ядер. Я обеспечиваю это, используя только два разных потока прямо сейчас.

Я могу измерить четкую разницу в отношении времени выполнения между использованием потоков, как описано, и перемещением ядер чередующихся, i. е .:

Loop: i = 0 to m 
    EnqueueKernel(Kernel i.1, Stream 1) 
    EnqueueKernel(Kernel i.2, Stream 2) 

против

Loop: i = 1 to n 
    Loop: j = 0 to m 
     EnqueueKernel(Kernel j.i, Stream i) 

Последнее приводит к более длительному времени выполнения.

Редактировать # 2: Изменено номера потоков, начинающихся с 1 (вместо 0, см. Комментарии ниже).

Edit # 3: Оборудование является NVIDIA Tesla M2090 (т.е. Ферми, вычислить способность 2,0)

+0

Возможно, вам понадобится использовать некоторые примитивы синхронизации потока для обеспечения требуемого порядка выполнения. Но не могли бы вы немного рассказать о том, как вы сделали свои измерения в своем вопросе, и не могли бы вы также подтвердить, что когда вы пишете «Stream 0», вы буквально не понимаете поток CUDA 0? – talonmies

+0

Я уточнил измерение (по крайней мере, надеюсь на это). С потоками я имею в виду примеры 'cudaStream_t', как описано в [CUDA C Programming Guide] (http://developer.download.nvidia.com/compute/DevZone/docs/html/C/doc/CUDA_C_Programming_Guide.pdf), раздел 3.2.5 (асинхронное параллельное выполнение). –

+2

Возможно, вы неправильно поняли то, что я просил - я имею в виду один из потоков потока CUDA потока 0, потому что поток 0 (поток по умолчанию) является синхронным. – talonmies

ответ

5

На Fermi (ака Compute Capability 2.0) аппаратные средства лучше чередовать ядро ​​запускает в несколько потоков, а не запускать все ядра в один поток, затем следующий поток и т. д. Это связано с тем, что аппаратное обеспечение может сразу запускать ядра для разных потоков, если ресурсов достаточно, тогда как если последующие запуски относятся к одному и тому же потоку, часто возникает задержка, уменьшая параллелизм. Именно по этой причине ваш первый подход работает лучше, и этот подход - тот, который вы должны выбрать.

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

+0

Можете ли вы дать мне источник, откуда это знание (в первом абзаце, а не во втором)? –

+0

В Разделе 3 Руководства по программированию CUDA 4.1 имеется информация. Однако после прочтения я вижу, что он явно не говорит о запуске ядра interleave. Я получил информацию от своих коллег в команде разработчиков NVIDIA CUDA. – harrism

+0

Спасибо за обновление. Я собираюсь пересмотреть свой код и предоставить больше информации/обновлений, если это возможно. –

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