Я написал небольшое ядро, суммирую 2^k элементов, используя параллельное сокращение. Ничего нового здесь .... Мой вектор хранится в глобальной памяти, я привязываю каждую часть вектора к другому блоку и уменьшаю каждый блок до одной позиции. Остальное я делаю в CPU.Синхронизация и глобальная память
__global__ void sum(real *v, long int s){
long int ix = threadIdx.x;
long int shift = blockIdx.x*blockDim.x;
long int h = blockDim.x/2;
while (h >= 1){
if (ix < h){
v[ix + shift] = v[2*ix + shift] + v[2*ix + 1 + shift];
}
__syncthreads();
h = h/2;
}
}
Код работает. Однако после тщательной проверки я понял, что, возможно, это не должно работать. Поэтому я запутался ... Может быть, что thread_id = 1, который суммирует элементы 2 и 3, записывает эту сумму в позицию 1 до того, как thread_id = 0 сможет читать элементы 0 и 1. Таким образом, результат недействителен.
Я предположил бы, что, чтобы быть безопасным, код должен быть
__global__ void sumsafe(real *v, long int s){
long int ix = threadIdx.x;
long int shift = blockIdx.x*blockDim.x;
real x = 0;
long int h = blockDim.x/2;
while (h >= 1){
if (ix < h){
x = v[2*ix + shift] + v[2*ix + 1 + shift];
}
__syncthreads();
if (ix < h){
v[ix + shift] = x;
}
__syncthreads();
h = h/2;
}
}
так, что я гарантирую, что все нити читать их значения, прежде чем они начинают менять их. Но, как я уже сказал, оба кода работают ... их время на самом деле также почти одинаково.
Почему это?
Я знаю, что GPU не гарантирует, что то, что один поток пишет в глобальную память, не видна другим потокам. Но это не гарантирует, что это всегда никогда не происходит.
Любые идеи!? Я работаю над GTX 1080.
Почему вы вызываете '_syncthreads()', если вы не используете разделяемую память? Кроме того, вы никогда не должны принимать конкретный порядок выполнения потоков. – pSoLT
Угадайте, вам просто повезло. – tera
Я звоню __syncthreads, чтобы гарантировать, что один поток записывает в глобальную память, видим другим потокам. Это вообще необходимо – cudarabit