【发布时间】:2016-06-08 13:30:21
【问题描述】:
我目前正在使用以下归约函数将数组中的所有元素与 CUDA 相加:
__global__ void reduceSum(int *input, int *input2, int *input3, int *outdata, int size){
extern __shared__ int sdata[];
unsigned int tID = threadIdx.x;
unsigned int i = tID + blockIdx.x * (blockDim.x * 2);
sdata[tID] = input[i] + input[i + blockDim.x];
__syncthreads();
for (unsigned int stride = blockDim.x / 2; stride > 32; stride >>= 1)
{
if (tID < stride)
{
sdata[tID] += sdata[tID + stride];
}
__syncthreads();
}
if (tID < 32){ warpReduce(sdata, tID); }
if (tID == 0)
{
outdata[blockIdx.x] = sdata[0];
}
}
但是,正如您从函数参数中看到的那样,我希望能够在一个归约函数内对三个单独的数组求和。现在显然一个简单的方法是启动内核三次并每次传递一个不同的数组,这当然可以正常工作。我现在只是把它写成一个测试内核,真正的内核最终会接受一个结构数组,我需要对每个结构的所有 X、Y 和 Z 值执行加法,这就是为什么我需要将它们全部汇总到一个内核中。
我已经为所有三个数组初始化并分配了内存
int test[1000];
std::fill_n(test, 1000, 1);
int *d_test;
int test2[1000];
std::fill_n(test2, 1000, 2);
int *d_test2;
int test3[1000];
std::fill_n(test3, 1000, 3);
int *d_test3;
cudaMalloc((void**)&d_test, 1000 * sizeof(int));
cudaMalloc((void**)&d_test2, 1000 * sizeof(int));
cudaMalloc((void**)&d_test3, 1000 * sizeof(int));
我不确定我应该为这种内核使用什么 Grid 和 Block 维度,并且我不完全确定如何修改归约循环以按我想要的方式放置数据,即 输出数组:
Block 1 Result|Block 2 Result|Block 3 Result|Block 4 Result|Block 5 Result|Block 6 Result|
Test Array 1 Sums Test Array 2 Sums Test Array 3 Sums
我希望这是有道理的。或者有没有更好的方法,只有一个归约函数,但能够返回 Struct.X、Struct.Y 或 struct.Z 的总和?
结构如下:
template <typename T>
struct planet {
T x, y, z;
T vx, vy, vz;
T mass;
};
我需要将所有的 VX 相加并存储它,所有的 VY 并存储它,以及所有的 VZ 并存储它。
【问题讨论】:
-
为什么不提供您想要求和的结构数组的实际定义?只是:
struct my_struct { int x,y,z;} data[1000];吗?这很重要的原因是因为这样的归约操作将受到内存带宽的限制。因此,了解内存中数据的组织以及访问模式对于实现最高性能非常重要。一个好的解决方案将优化内存访问模式以优化可用内存带宽的使用。 -
对不起,你是对的,我已经用结构的定义更新了主帖。