【发布时间】:2012-09-18 08:50:01
【问题描述】:
这是我第二次尝试 CUDA 程序和并行开发。
我试图找出点积两个数组的原因。
例子:
给定
A = [1 2 3]
B = [4 5 6]
C[0] = (1)(4) + (1)(5) + (1)(6)
C[1] = (2)(4) + (2)(5) + (2)(6)
C[2] = (3)(4) + (3)(5) + (3)(6)
我初始化 2 个数组 A 和 B ,随机填充一个范围内的元素,然后将 A 中的每个元素与 B 中的每个元素相乘,并将乘积的总和存储在标识为 @987654324 的第三个数组中@。我已将数组 A、B 和 C 的大小设置为 100。
这给了我 10'000 次乘法,我使用 100 个块和 128 个线程(由于 warp 大小)并行化这些乘法。
这是我的内核函数:
__global__ void kernel(float *a, float *b, float *c, const int N) {
if( threadIdx.x < N )
c[blockIdx.x] += a[blockIdx.x] * b[threadIdx.x];
}
这是我的推理,因为聚合必须在C 中累积,它与A 中的枢轴索引具有相同的索引,因此我可以重用blockidx.x 并且“应该”正常工作;但事实并非如此。
我怀疑C 索引在线程更改时被清除或不共享,但我真的不确定这是我寻求建议的原因。
这是完整的代码,我已经明确避免使用 HANDLE_ERROR 函数包装器来缩短
#include <stdio.h>
#include <cuda.h>
#include <time.h>
#define M 100
__global__ void kernel(float *a, float *b, float *c, const int N) {
if(threadIdx.x < N)
c[blockIdx.x] += a[blockIdx.x] * b[threadIdx.x];
}
void init_array(float*, const int);
void fill_array(float*, const int, const float);
void print_array(float*, const int, *char);
int main (void) {
srand( time(NULL) );
float a[M], b[M], c[M] = { 0.0 };
float *dev_a, *dev_b, *dev_c;
const int S = sizeof(float) * M;
init_array(a, M);
init_array(b, M);
print_array(a, M, "a");
print_array(b, M, "b");
print_array(c, M, "c");
cudaMalloc((void**)&dev_a, S);
cudaMalloc((void**)&dev_b, S);
cudaMalloc((void**)&dev_c, S);
cudaMemcpy(dev_a, a, S, cudaMemcpyHostToDevice);
cudaMemcpy(dev_b, b, S, cudaMemcpyHostToDevice);
cudaMemcpy(dev_c, c, S, cudaMemcpyHostToDevice);
kernel<<<M, M + 28>>>(dev_a, dev_b, dev_c, M);
cudaMemcpy(c, dev_c, S, cudaMemcpyDeviceToHost);
cudaFree(dev_a);
cudaFree(dev_b);
cudaFree(dev_c);
print_array(c, M, "c");
return 0;
}
void init_array(float *a, const int N) {
int i;
for(i=0; i<N; i++)
a[i] = rand() % M + 1;
}
void fill_array(float *a, const int N, const float v) {
int i;
for(i=0; i<N; i++)
a[i] = v;
}
void print_array(float *a, const int N, char *d) {
int i;
for(i=0; i<N; i++)
printf("\n%s[%d]: %f",d, i, a[i]);
}
【问题讨论】:
-
你能提供一个你期望的结果样本吗?例如,如果 a=[1 2 3] and b=[4 5 6] and c=[0 0 0] 那么最后的 c 应该是什么。
-
好吧,如果我们用 3.0 填充
A和B,我们应该得到3 * 3 * 100 = 900,C的每个元素中都有 900。 -
现在,根据您的评论,鉴于
A=[1 2 3]和B=[4 5 6],我们将拥有(1)(4) + (1)(5) + (1)(6) = 15。 -
好的。请注意,您正在通过块的并发线程写入全局内存的相同位置。您应该使用原子操作来获得正确的答案。我会尽快提供代码。
标签: c parallel-processing cuda