У меня есть следующий алгоритм:Снижение или атомный оператор на неизвестных глобальных индексов массива
__global__ void Update(int N, double* x, double* y, int* z, double* out)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < N)
{
x[i] += y[i];
if (y[i] >= 0.)
out[z[i]] += x[i];
else
out[z[i]] -= x[i];
}
}
Важно отметить, что из меньше х. Скажем, x, y и z всегда одного и того же размера, скажем 1000, а out всегда меньше, скажем, 100. z - это индексы, которые соответствуют каждому из x и y.
Это все находка, кроме обновлений. Там могут быть конфликты между потоками, поскольку z не содержит только уникальные значения и имеет дубликаты. Поэтому в настоящее время это реализовано с атомными версиями atomicAdd и вычитанием с помощью сравнения и свопинга. Это, очевидно, дорого и означает, что мое ядро занимает 5-10 раз дольше.
Я хотел бы уменьшить это, но единственный способ, которым я могу это сделать, - это для каждого потока иметь свою собственную версию (которая может быть большой, 10000+, X 10000+ потоков). Это означало бы, что я установил 10000 double [10000] (возможно, в shared?), Чтобы вызвать мое ядро, а затем суммировать эти массивы, возможно, в другом ядре. Неужели должен быть более элегантный способ сделать это?
Возможно, стоит отметить, что x, y, z и out находятся в глобальной памяти. Поскольку мое ядро (у меня есть другие подобные) очень просто, я не решил копировать бит в общий (nvvp на ядре показывает равные вычисления и память, поэтому я думаю, что не так много производительности при добавлении накладных расходов на перенос данных из глобальное разделение и возвращение назад, любые мысли?).
Что это: 'out [i [z [i]]'? Вы имели в виду 'out [[z [i]]'? –
@RobertCrovella oops, извините, да, изменено. z представляет собой массив «индексов». Каждый входной элемент x и y соответствует разному через z. Добавил еще несколько объяснений, я понял, что не стал сожалеть. – James
@James: Этот последний комментарий неверен? Разве не весь вопрос о том, что каждый элемент х и у * не * соответствует другому через z? В противном случае сложность атомных операций не требуется - ваше ядро в основном будет «сплавленным добавлением-разбросом». – talonmies