Для меня загадка, как работает разделяемая память на устройствах cuda. Мне было любопытно посчитать потоки, имеющие доступ к одной и той же общей памяти. Для этого я написал простую программу
#include <cuda_runtime.h>
#include <stdio.h>
#define nblc 13
#define nthr 1024
//------------------------@device--------------------
__device__ int inwarpD[nblc];
__global__ void kernel(){
__shared__ int mywarp;
mywarp=0;
for (int i=0;i<5;i++) mywarp += (10000*threadIdx.x+1);
__syncthreads();
inwarpD[blockIdx.x]=mywarp;
}
//------------------------@host-----------------------
int main(int argc, char **argv){
int inwarpH[nblc];
cudaSetDevice(2);
kernel<<<nblc, nthr>>>();
cudaMemcpyFromSymbol(inwarpH, inwarpD, nblc*sizeof(int), 0, cudaMemcpyDeviceToHost);
for (int i=0;i<nblc;i++) printf("%i : %i\n",i, inwarpH[i]);
}
и запустил его на графическом процессоре K80. Поскольку несколько потоков имеют доступ к одной и той же переменной общей памяти, я ожидал, что эта переменная будет обновляться 5 * nth раз, хотя и не в одном и том же цикле из-за конфликта банков. Однако выходные данные показывают, что общая переменная mywarp была обновлена только 5 раз. Для каждого блока разные потоки выполняли эту задачу:
0 : 35150005
1 : 38350005
2 : 44750005
3 : 38350005
4 : 51150005
5 : 38350005
6 : 38350005
7 : 38350005
8 : 51150005
9 : 44750005
10 : 51150005
11 : 38350005
12 : 38350005
Вместо этого я ожидал
523776*10000+5*1024=5237765120
для каждого блока. Может кто-нибудь любезно объяснить мне, где мое понимание общей памяти терпит неудачу. Я также хотел бы знать, как возможно, чтобы все потоки в одном блоке обращались (обновляли) к одной и той же общей переменной. Я знаю, что это невозможно в том же цикле MP. Сериализация мне подходит, потому что это будет редкое событие.