2014-01-19 4 views
0

CUDA Am пытается построить структуру индекса в коде ядра:Построение индекса с использованием атомно-операцию в

atomicCAS((int*)&index[val], -1, atomicAdd((unsigned int*)&index_pos, 1)); 

индекс [] объявлен как динамический общий массив памяти и инициализируется с -1, index_pos объявлен как изменчивый.

Интуиция такова: только первый поток в блоке должен инициализировать индекс и увеличивать index_pos. Однако я заметил, что index_pos увеличивается несколько раз конфликтующими потоками. Почему это происходит?

+0

Все потоки (по крайней мере, по умолчанию) будут увеличивать 'index_pos' до того, как что-либо еще произойдет. Почему ваша интуиция заключается в том, что только первый поток в блоке должен это сделать? Эта строка исходного кода преобразуется в последовательность инструкций языка ассемблера, которые выполняются в режиме блокировки с помощью основы. Если один поток выполняет 'atomicAdd', то все потоки в warp также будут выполнять его. Возможно, вы должны сбросить инструкции по сборке ('cuobjdump -sass my_app') и подумать о том, что там происходит. Я думаю, это будет поучительно. –

+0

Как только первый поток получит блокировку и выполнит операцию CAS (index [val] = index_pos ++), значение индекса [val] больше не будет равным -1. Другие потоки не смогут войти в блок CAS. Разве это не так? – Ty1er

+0

Нет, это неправильно. Возможно, вам стоит перечитать мой комментарий. Единственная строка исходного кода, которую вы указали, не выполняется во всех отношениях атомарно. Примерно первая операция, которая выполняется, представляет собой «atomicAdd», и это будет выполняться всеми потоками (по крайней мере, в warp). Я думаю, что будет поучительно, если вы подумаете о том, что этот факт разбит на последовательность инструкций языка ассемблера. Вся последовательность команд сборки не выполняется атомарно. –

ответ

1

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

Пример:

atomicAdd(atomicAdd(x, 1), 1); 

не действует как

atomicAdd(x, 2); 

но:

atomicAdd(x, 1); 
atomicAdd(x, 1); 

EDIT ПОСЛЕ Комментарий:

Havi ng из вашего комментария Я бы обеспечил описанную функциональность по следующему коду:

if(index[val] == -1) { // this is just an optimization 
    atomicCAS((int*)&index[val], -1, threadId); // initialization by the only thread 
} 

__threadfence_block(); 

if(index[val] == threadId) { 
    index_pos++; //index_pos will be incremented only "once" 
} 
+0

моя первая версия не использовала atomicAdd 'atomicCAS ((int *) & index [val], -1, index_pos ++); '.Я хочу, чтобы index_pos увеличивался, только если индекс [val] не инициализирован (-1). операция atomicCAS обеспечивает именно эту семантику, не так ли? – Ty1er