2012-09-25 52 views
1

环路我在Java中下面的代码:嵌套与+ = assignement

float in[][] = new float[2][2]; 

float B[] = new float[2]; 
float A[] = new float[2]; 
float res[] = new float[A[0].length]; 

for(float r : res){ 
    r = 0; 
} 

for (int i = 0; i < A[0].length; i++) { 
    for (int j = 0; j < B[0].length; j++) { 
     res[i] += A[j] * in[j][i]; 
} 

我简化它最多,所以你不应该在那里寻找一个真正的逻辑:)。

由于循环中的+ =语句,我在CUDA中将其转换了一些时间,所以很困难。

我开始是这样的:

extern "C" 
__global__ void filter(float* in, float* A, float* B, float* res, int in_size){ 

    unsigned int x = blockIdx.x*blockDim.x + threadIdx.x; 
    unsigned int y = blockIdx.y*blockDim.y + threadIdx.y; 

    res[x] = A[y] * in[x + y * in_width]; 

} 

,但很快意识到它不能,因为所有尝试设置相同的变量线程的工作。

我读点积in this presentation, 的例子,但我实在不明白如何去适应,与我需要两个维度为英寸

我不要求一个完整的解决方案,但任何方向肯定会被赞赏。

Thx,

回答

1

太多的CUDA杀死了我的头。

我在内核中展开了一个循环,发现了一个部分解决方案。 这是它看起来像现在:

extern "C" 
__global__ void filter(float* in, float* A, float* res, const int in_width, const int sizeB){ 
    unsigned int x = blockIdx.x*blockDim.x + threadIdx.x; 
    int i = 0; 

    for(i = 0; i < sizeB; i++){ 
     res[x] += A[i] * in[i + x * in_width]; 
    } 

} 

我相信我能找到更好的,但我想我会用这根棍子今天:)

+0

您还在增加所有线程的res,这不应该工作。如果它只是浮动,你可以使用原子(应该是缓慢的),或者你可以为每个块实现适当的二叉树缩减,然后总结CPU上的块和。 – Reguj

+0

它确实有效。我正在增加循环中的一个元素为同一个线程。在这种情况下,每个x对应一个单独的线程,因此循环是安全的。缺点是每个线程都必须执行一个循环,所以我只优化了一半的进程 – jlengrand

+1

这看起来像我会先并行化它。你需要将res数组初始化为零,我假设你在这个内核之外进行操作。只需将res [x] = 0;在内核之前的循环之前。接下来是优化... – harrism

0

您可以拆分乘法作业A [j] * in [A] [i] in A [0] .length * B [0] .length线程,并且可以将乘法结果归纳为NVIDIA sdk中使用共享内存的类似缩减样本

+0

然后我需要一个sizeA * sizeB数组。当我在桌子上工作时可能会出现问题 – jlengrand