CUDA Am пытается построить структуру индекса в коде ядра:Построение индекса с использованием атомно-операцию в
atomicCAS((int*)&index[val], -1, atomicAdd((unsigned int*)&index_pos, 1));
индекс [] объявлен как динамический общий массив памяти и инициализируется с -1, index_pos объявлен как изменчивый.
Интуиция такова: только первый поток в блоке должен инициализировать индекс и увеличивать index_pos. Однако я заметил, что index_pos увеличивается несколько раз конфликтующими потоками. Почему это происходит?
Все потоки (по крайней мере, по умолчанию) будут увеличивать 'index_pos' до того, как что-либо еще произойдет. Почему ваша интуиция заключается в том, что только первый поток в блоке должен это сделать? Эта строка исходного кода преобразуется в последовательность инструкций языка ассемблера, которые выполняются в режиме блокировки с помощью основы. Если один поток выполняет 'atomicAdd', то все потоки в warp также будут выполнять его. Возможно, вы должны сбросить инструкции по сборке ('cuobjdump -sass my_app') и подумать о том, что там происходит. Я думаю, это будет поучительно. –
Как только первый поток получит блокировку и выполнит операцию CAS (index [val] = index_pos ++), значение индекса [val] больше не будет равным -1. Другие потоки не смогут войти в блок CAS. Разве это не так? – Ty1er
Нет, это неправильно. Возможно, вам стоит перечитать мой комментарий. Единственная строка исходного кода, которую вы указали, не выполняется во всех отношениях атомарно. Примерно первая операция, которая выполняется, представляет собой «atomicAdd», и это будет выполняться всеми потоками (по крайней мере, в warp). Я думаю, что будет поучительно, если вы подумаете о том, что этот факт разбит на последовательность инструкций языка ассемблера. Вся последовательность команд сборки не выполняется атомарно. –