Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 如何在CUDA中不使用原子进行求和计算_Performance_Optimization_Cuda_Sum - Fatal编程技术网

Performance 如何在CUDA中不使用原子进行求和计算

Performance 如何在CUDA中不使用原子进行求和计算,performance,optimization,cuda,sum,Performance,Optimization,Cuda,Sum,在下面的代码中,如何在不使用atomicAdd的情况下计算sum\u array值 核方法 __global__ void calculate_sum( int width, int height, int *pntrs, int2 *sum_array ) { int row = blockIdx.y

在下面的代码中,如何在不使用atomicAdd的情况下计算sum\u array

核方法

__global__ void calculate_sum( int width,
                               int height,
                               int *pntrs,
                               int2 *sum_array )
{
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;

    if ( row >= height || col >= width ) return;

    int idx = pntrs[ row * width + col ];

    //atomicAdd( &sum_array[ idx ].x, col );

    //atomicAdd( &sum_array[ idx ].y, row );

    sum_array[ idx ].x += col;

    sum_array[ idx ].y += row;
}
启动内核

    dim3 dimBlock( 16, 16 );
    dim3 dimGrid( ( width + ( dimBlock.x - 1 ) ) / dimBlock.x, 
                  ( height + ( dimBlock.y - 1 ) ) / dimBlock.y );

归约是这类问题的总称。进一步解释,请参阅,其他示例请使用谷歌

解决这个问题的一般方法是在线程块内对全局内存段进行并行求和,并将结果存储在全局内存中。然后,将部分结果复制到CPU内存空间,使用CPU对部分结果求和,然后将结果复制回GPU内存。您可以通过对部分结果执行另一个并行求和来避免内存占用


另一种方法是为CUDA使用高度优化的库,如推力或CUDPP,其中包含执行这些操作的函数。

缩减是此类问题的通用名称。进一步解释,请参阅,其他示例请使用谷歌

解决这个问题的一般方法是在线程块内对全局内存段进行并行求和,并将结果存储在全局内存中。然后,将部分结果复制到CPU内存空间,使用CPU对部分结果求和,然后将结果复制回GPU内存。您可以通过对部分结果执行另一个并行求和来避免内存占用

另一种方法是为CUDA使用高度优化的库,如包含函数的推力或CUDPP。

我的CUDA非常生锈,但大致上就是这样做的(由“CUDA示例”提供,我强烈建议您阅读):

  • 对需要求和的数组进行更好的分区:CUDA中的线程是轻量级的,但不能太多,以至于只需两次求和就可以生成一个线程,并希望得到任何性能上的好处
  • 此时,每个线程的任务将是对数据的一部分求和:创建一个共享int数组,其大小与线程数相同,每个线程将保存它计算的部分和
  • 同步线程并减少共享内存阵列:
  • (请将其视为伪代码)

    //在片上求和的代码,本质上是每个线程子集上的循环
    //并在“localsum”(局部变量)上累加
    ...
    //将结果保存在共享内存中
    部分[threadidx]=localsum;
    //同步线程:
    __同步线程();
    //从现在起,所有计算的结果都将填入partial:您可以减少partial
    //我们将以不识字的方式,使用一个线程(它可以很容易地并行化)
    如果(threadidx==0){
    对于(i=1;i
    然后你离开:部分[0]将保留你的总和(或计算)

    请参阅“CUDA by example”中的点积示例,以了解有关该主题的更严格的讨论以及大约在O(log(n))中运行的简化算法

    希望这有帮助

    我的Cuda非常生锈,但这大致就是你如何做到的(由“Cuda举例”提供,我强烈建议你阅读):

  • 对需要求和的数组进行更好的分区:CUDA中的线程是轻量级的,但不能太多,以至于只需两次求和就可以生成一个线程,并希望得到任何性能上的好处
  • 此时,每个线程的任务将是对数据的一部分求和:创建一个共享int数组,其大小与线程数相同,每个线程将保存它计算的部分和
  • 同步线程并减少共享内存阵列:
  • (请将其视为伪代码)

    //在片上求和的代码,本质上是每个线程子集上的循环
    //并在“localsum”(局部变量)上累加
    ...
    //将结果保存在共享内存中
    部分[threadidx]=localsum;
    //同步线程:
    __同步线程();
    //从现在起,所有计算的结果都将填入partial:您可以减少partial
    //我们将以不识字的方式,使用一个线程(它可以很容易地并行化)
    如果(threadidx==0){
    对于(i=1;i
    然后你离开:部分[0]将保留你的总和(或计算)

    请参阅“CUDA by example”中的点积示例,以了解有关该主题的更严格的讨论以及大约在O(log(n))中运行的简化算法

    希望这有帮助

    // Code to sum over a slice, essentially a loop over each thread subset
    // and accumulate over "localsum" (a local variable)
    ...
    
    // Save the result in the shared memory
    partial[threadidx] = localsum;
    
    // Synchronize the threads:
    __syncthreads();
    
    // From now on partial is filled with the result of all computations: you can reduce partial
    // we'll do it the illiterate way, using a single thread (it can be easily parallelized)
    if(threadidx == 0) {
        for(i = 1; i < nthreads; ++i) {
            partial[0] += partial[i];
        }
    }