优化Cuda内核关于数组的规范化

时间:2012-11-14 10:37:03

标签: cuda gpu gpgpu gpu-programming pycuda

我正在尝试按如下方式规范化数组。

  1. 选择数组的前两个元素,找到总和并使用该总和除以它们。
  2. 对其余元素执行相同操作。
  3. 工作正常。但是当我增加阵列的尺寸时,时间复杂性就会出现。我在下面给出了我的代码。

    import pycuda.driver as drv
    import pycuda.autoinit
    from pycuda.compiler import SourceModule
    import numpy as np
    
    mod=SourceModule("""
    __global__ void addition(float* a,float* c,float* d)
    {
    int i=blockIdx.y*blockDim.y+threadIdx.y;
    for (i=0;i<=4;++i)
    {
        int sum=0.0;
        for (int j=0;j<=1;++j)
        {
            sum+=a[2*i+j];
        }
    c[i]=sum;
    }
    for (i=0;i<=4;i++)
    {
        for (int j=0;j<=1;++j)
        {
            d[2*i+j]=a[2*i+j]/c[i];
        }
    }
    }
    """)
    
    addition=mod.get_function("addition")
    a=np.array([1,2,3,1,2,3,2,1]).astype(np.float32)
    c=np.zeros_like(a)
    d=np.zeros_like(a)
    addition(drv.In(a),drv.InOut(c),drv.InOut(d),block=(1,8,1))
    print d
    

    d的结果是[0.33333334 0.66666669 0.75 0.25 0.40000001 0.60000002 0.666666669 0.33333334]。任何人都可以建议一些优化代码的想法吗?

1 个答案:

答案 0 :(得分:1)

如果您的真实应用只是将a中的一对值相加,则将该总和存储在c中,然后将该值与该值一起归一化并将其存储在d中,这样的事情是合理的:

__global__ void addition(float* a, float* c, float* d)
{
    int idx = threadIdx.x + blockDim.x*blockIdx.x;

    float2* avec = reinterpret_cast<float2*>(a);
    float2* dvec = reinterpret_cast<float2*>(d);

    float2 val = avec[idx];
    float sum = val.x + val.y;
    val.x \= sum;
    val.y \= sum;

    c[idx] = sum;
    dvec[idx] = val;     
} 

[免责声明:用浏览器编写,从未编译过,从未测试过,不保证不会让你的GPU着火,自担风险使用]

这里使用向量类型来提高内存吞吐量,每个线程处理一对值。对于N值,运行N / 2个线程。如果您有超过131070个输入值(因此65535对),则需要修改内核以处理多个输入。如果出现这样的可能性,我会将其作为读者的练习。