модель производителя / потребителя и параллельные ядра - PullRequest
0 голосов
/ 04 марта 2011


Я пишу программу cuda, которую можно интерпретировать как модель производителя / потребителя.

Есть два ядра, выдает данные в память устройства,
и другое ядро ​​произвело данные.

Количество исходящих потоков задается в два раза больше 32, что является размером основы.
и каждый перекос ждет до получения 32 данных.

У меня тут какая-то проблема.
Если потребительское ядро ​​загружено позже, чем производитель,
программа не останавливается.
Иногда программа запускается неопределенно, даже если потребитель загружается первым.

Я спрашиваю, есть ли в CUDA хорошая модель реализации производителя / потребителя?
Кто-нибудь может дать мне направление или ссылку?

вот скелет моего кода.

**kernel1**:

while LOOP_COUNT
    compute something
    if SOME CONDITION
        atomically increment PRODUCE_COUNT          
        write data into DATA            
atomically increment PRODUCER_DONE

**kernel2**:
while FOREVER
    CURRENT=0
    if FINISHED CONDITION
        return
    if PRODUCER_DONE==TOTAL_PRODUCER && CONSUME_COUNT==PRODUCE_COUNT
        return
    if (MY_WARP+1)*32+(CONSUME_WARPS*32*CURRENT)-1 < PRODUCE_COUNT
        process the data
        if SOME CONDITION
            set FINISHED CONDITION true
        increment CURRENT
    else if PRODUCUER_DONE==TOTAL_PRODUCER
        if currnet*32*CONSUME_WARPS+THREAD_INDEX < PRODUCE_COUNT
            process the data
            if SOME CONDITION
                set FINISHED CONDITION true
            increment CURRENT

1 Ответ

2 голосов
/ 04 марта 2011

Поскольку вы не предоставили реальный код, трудно определить, где находится ошибка.Обычно сценарий правильный, но проблема кроется в деталях.

Одна из возможных проблем, о которых я могу подумать:

По умолчанию в CUDA нет гарантиизапись глобальной памяти одним ядром будет видна другому ядру, за исключением атомарных операций.Может случиться так, что ваше первое ядро ​​увеличит значение PRODUCER_DONE, но в DATA все еще нет данных.

К счастью, вам предоставляется интристическая функция __threadfence(), которая останавливает выполнение текущего потока, пока данные не будутвидимый.Вы должны поместить его до атомарного увеличения PRODUCER_DONE.Ознакомьтесь с главой B.5 в Руководстве по программированию CUDA.

Другая проблема, которая может появиться или не появиться:

С точки зрения kernel2, компилятор можетвычтите, что PRODUCE_COUNT после прочтения никогда не изменится.Компилятор может оптимизировать код таким образом, чтобы после загрузки в регистр он снова использовал свое значение вместо того, чтобы каждый раз запрашивать глобальную память.Решение?Используйте volatile или прочитайте значение с помощью другой атомарной операции.

(Правка) Третий выпуск:

Я забыл еще об одной проблеме.На картах Pre-Fermi (GeForce до 400-й серии) вы можете запускать только одно ядро ​​за раз.Таким образом, если вы запланируете запуск производителя после потребителя, система будет ждать окончания ядра потребителя, прежде чем ядро ​​производителя начнет свое выполнение.Если вы хотите, чтобы оба выполнялись одновременно, поместите оба в одно ядро ​​и создайте ветвь if, основанную на некотором блочном индексе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...