首先:很抱歉,如果这个主题做得不好(这是我的第一个主题) 我目前正在尝试在NVIDIA上学习GPU计算,但是 我对CUDA的__syncthreads()方法有问题,我认为它不起作用。我尝试在网络上进行搜索,但未找到解决方法。
__global__ void stencil_1d(int *in, int *out) {
__shared__ int temp[BLOCK_SIZE + 2 * RADIUS]; // Création de la mémoire partagée avec tout les threads d'un même block
int gindex = threadIdx.x + blockIdx.x * blockDim.x;
int lindex = threadIdx.x + RADIUS;
/*for (int i = 0; i < N*sizeof(int); i++)
printf("%i ---i=%i \n", in[i], i);*/
// Déplacer les éléments d'entrées sur la mémoire partagée
temp[lindex] = in[gindex];
if (threadIdx.x < RADIUS) {
temp[lindex - RADIUS] = in[gindex - RADIUS]; // Récuprère le Halo avant les valeurs du block
temp[lindex + BLOCK_SIZE] = in[gindex + BLOCK_SIZE]; // Récupère le Halo après les valeurs du block
}
__syncthreads(); // Synchronisation des Threads d'un même Block
int result = 0;
for (int offset = -RADIUS; offset <= RADIUS ; offset++)
result += temp[lindex + offset];
out[gindex] = result;
}
当我取消对for
的注释时,程序可以正常运行,但是目前for
变量中没有out
我的图表返回-842150451。
主要代码:
int main()
{
int size = N * sizeof(int);
/******************** Utilisation de la fonction GPU stencil_1d ********************/
int *in, *out; // Variable sur la mémoire Host
int *d_in, *d_out; //Variable sur la mémoire Device
// Allocation de la mémore aux variables sur le Device
cudaMalloc((void**)&d_in, size);
cudaMalloc((void**)&d_out, size);
// Allocation de la mémoire aux variables de Host
in = (int*)malloc(size); random_ints(in, N);
out = (int*)malloc(size);
// Copie des valeurs des variables de Host vers Device
cudaMemcpy(d_in, in, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_out, out, size, cudaMemcpyHostToDevice);
// Exécution de la fonction sur le Device (ici 3 Blocks, 10 Threads)
stencil_1d <<<N/THREADS_PER_BLOCK, THREADS_PER_BLOCK>>>(d_in, d_out);
// Récupération de la variable out de Device vers Host
cudaMemcpy(out, d_out, size, cudaMemcpyDeviceToHost);
// Affichage du résultat
for(int i=0; i<size; i++)
printf("%i ---i=%i \n", out[i], i);
// Libération de la mémoire prise par les variables sur Host
free(in); free(out);
// Libération de la mémoire prise par les variables sur le Device
cudaFree(d_in); cudaFree(d_out);
return 0;
}
如果忘记了: 定义:
#define N 30
#define THREADS_PER_BLOCK 10
#define BLOCK_SIZE (N/THREADS_PER_BLOCK)
#define RADIUS 3
random_ints代码:
void random_ints(int *var, int n) // Attribue une valeur à toutes le composantes des variables
{
int i;
for (i = 0; i < n; i++)
var[i] = 1;
}
在此先感谢您的回答。
答案 0 :(得分:2)
This code最初是为教学而设计的;它有一些缺陷。
首先,每当遇到CUDA代码问题时,我建议使用proper CUDA error checking并使用cuda-memcheck
运行代码(请参阅下面的示例cuda-memcheck
)。如果您在寻求他人帮助之前进行了此操作,并在问题中提供了错误信息,则可能会帮助其他人帮助您。
如果使用cuda-memcheck
运行此代码,它将指示访问全局内存和共享内存时均出现错误。
您选择的BLOCK_SIZE
不正确。应将其设置为等于THREADS_PER_BLOCK
,而不是(N/THREADS_PER_BLOCK)
。看来您打算以3个块(每个块10个线程)运行此内核,因此我们将对其进行处理。
这些行将越界索引:
if (threadIdx.x < RADIUS) {
temp[lindex - RADIUS] = in[gindex - RADIUS]; // Récuprère le Halo avant les valeurs du block
temp[lindex + BLOCK_SIZE] = in[gindex + BLOCK_SIZE]; // Récupère le Halo après les valeurs du block
例如,在第一个块中,第一个线程(threadIdx.x
为0),gindex
为0,因此计算gindex - RADIUS
将为-3。那是不正确的。
此for循环不正确:
for(int i=0; i<size; i++)
应该是:
for(int i=0; i<N; i++)
当我修复这些问题时,您的代码会正确运行,并为我带来明智的结果:
$ cat t280.cu
#define N 30
#define THREADS_PER_BLOCK 10
#define BLOCK_SIZE THREADS_PER_BLOCK
#define RADIUS 3
#include <stdio.h>
void random_ints(int *var, int n) // Attribue une valeur à toutes le composantes des variables
{
int i;
for (i = 0; i < n; i++)
var[i] = 1;
}
__global__ void stencil_1d(int *in, int *out) {
__shared__ int temp[BLOCK_SIZE + 2 * RADIUS]; // Création de la mémoire partagée avec tout les threads d'un même block
int gindex = threadIdx.x + blockIdx.x * blockDim.x;
int lindex = threadIdx.x + RADIUS;
/*for (int i = 0; i < N*sizeof(int); i++)
printf("%i ---i=%i \n", in[i], i);*/
// Déplacer les éléments d'entrées sur la mémoire partagée
temp[lindex] = in[gindex];
if (threadIdx.x < RADIUS) {
temp[lindex - RADIUS] = (gindex >= RADIUS)?in[gindex - RADIUS]:0; // Récuprère le Halo avant les valeurs du block
temp[lindex + BLOCK_SIZE] = ((gindex + BLOCK_SIZE)<N)?in[gindex + BLOCK_SIZE]:0; // Récupère le Halo après les valeurs du block
}
__syncthreads(); // Synchronisation des Threads d'un même Block
int result = 0;
for (int offset = -RADIUS; offset <= RADIUS ; offset++)
result += temp[lindex + offset];
out[gindex] = result;
}
int main()
{
int size = N * sizeof(int);
/******************** Utilisation de la fonction GPU stencil_1d ********************/
int *in, *out; // Variable sur la mémoire Host
int *d_in, *d_out; //Variable sur la mémoire Device
// Allocation de la mémore aux variables sur le Device
cudaMalloc((void**)&d_in, size);
cudaMalloc((void**)&d_out, size);
// Allocation de la mémoire aux variables de Host
in = (int*)malloc(size); random_ints(in, N);
out = (int*)malloc(size);
// Copie des valeurs des variables de Host vers Device
cudaMemcpy(d_in, in, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_out, out, size, cudaMemcpyHostToDevice);
// Exécution de la fonction sur le Device (ici 3 Blocks, 10 Threads)
stencil_1d <<<N/THREADS_PER_BLOCK, THREADS_PER_BLOCK>>>(d_in, d_out);
// Récupération de la variable out de Device vers Host
cudaMemcpy(out, d_out, size, cudaMemcpyDeviceToHost);
// Affichage du résultat
for(int i=0; i<N; i++)
printf("%i ---i=%i \n", out[i], i);
// Libération de la mémoire prise par les variables sur Host
free(in); free(out);
// Libération de la mémoire prise par les variables sur le Device
cudaFree(d_in); cudaFree(d_out);
return 0;
}
$ nvcc -o t280 t280.cu
$ cuda-memcheck ./t280
========= CUDA-MEMCHECK
4 ---i=0
5 ---i=1
6 ---i=2
7 ---i=3
7 ---i=4
7 ---i=5
7 ---i=6
7 ---i=7
7 ---i=8
7 ---i=9
7 ---i=10
7 ---i=11
7 ---i=12
7 ---i=13
7 ---i=14
7 ---i=15
7 ---i=16
7 ---i=17
7 ---i=18
7 ---i=19
7 ---i=20
7 ---i=21
7 ---i=22
7 ---i=23
7 ---i=24
7 ---i=25
7 ---i=26
6 ---i=27
5 ---i=28
4 ---i=29
========= ERROR SUMMARY: 0 errors
$
我们在模版输出的每一端得到4,5,6的原因是由于我们在内核中对上面第2项的限制,以避免越界索引。您可以根据需要更改此边界行为。
另外一条评论:现在,您的代码选择N
和THREADS_PER_BLOCK
以便它们可以被整除。只要您这样做(并遵守其他限制,例如每块最大线程数为1024),就可以使用此代码。为了获得other changes should be made的充分灵活性,但是我在这里描述的内容应该足以使您克服这些错误。