CUDA在给定数组中找到最大值

时间:2011-03-11 06:17:51

标签: cuda

我尝试开发一个小型CUDA程序,用于查找给定数组中的最大值,

int input_data[0...50] = 1,2,3,4,5....,50

max_valueinput_data[0]的第一个值初始化, 最终答案存储在result[0]中。 内核给出0作为最大值。我不知道问题是什么。 我执行了1个50个线程。

__device__ int lock=0;

__global__ void max(float *input_data,float *result)
{
     float max_value = input_data[0];
     int  tid = threadIdx.x;

     if( input_data[tid] > max_value)
     {
         do{} while(atomicCAS(&lock,0,1));
         max_value=input_data[tid];
         __threadfence();
         lock=0;
      }

    __syncthreads();
    result[0]=max_value;  //Final result of max value 
}

尽管有内置功能,但我正在练习小问题。

4 个答案:

答案 0 :(得分:4)

您正在尝试设置“关键部分”,但是这种CUDA方法可能导致整个程序挂起 - 尽可能避免使用它。

为什么您的代码会挂起?

您的内核(__global__函数)由32个线程组执行,称为 warps 。单个warp中的所有线程都是同步执行的。因此,warp将在您的do{} while(atomicCAS(&lock,0,1))中停止,直到所有线程从您的warp成功获得锁定。但显然,您希望防止多个线程同时执行关键部分。这导致了一个悬念。

替代解决方案

您需要的是“并行缩减算法”。你可以在这里开始阅读:

答案 1 :(得分:1)

您的代码有潜在的竞争。我不确定你是否在共享内存中定义了'max_value'变量,但两者都错了。

1)如果'max_value'只是一个局部变量,那么每个线程都保存它的本地副本,它不是实际的最大值(它们只是input_data [0]和input_data [tid]之间的最大值) 。在最后一行代码中,所有线程都将结果[0]写入自己的max_value,这将导致未定义的行为。

2)如果'max_value'是共享变量,49个线程将进入if-statements块,并且他们将尝试使用锁一次更新一个'max_value'。但是没有定义49个线程中的执行顺序,因此某些线程可能会将实际最大值覆盖为较小的值。您需要在关键部分再次比较最大值。

答案 2 :(得分:1)

Max是'减少' - 查看SDK中的减少示例,并执行max而不是求和。

白皮书有点陈旧但仍然相当有用:

http://developer.download.nvidia.com/compute/cuda/1_1/Website/projects/reduction/doc/reduction.pdf

最后的优化步骤是使用'warp synchronous'编码来避免不必要的__syncthreads()调用。

它需要至少2个内核调用 - 一个用于将一堆中间max()值写入全局内存,然后另一个用于获取该数组的max()。

如果要在单个内核调用中执行此操作,请查看threadfenceReduction SDK示例。使用__threadfence()和atomicAdd()来跟踪进度,然后在所有块完成中间结果写入后,有1个块进行最终减少。

答案 3 :(得分:-1)

变量有不同的访问权限。当您通过设备定义变量时,变量将被放置在GPU全局内存中,并且网格中的所有线程都可以访问它,共享将变量放在块共享内存中只能通过该块的线程访问,如果您不使用任何关键字,如 float max_value ,则该变量放在线程寄存器上,它可以是只在该线程中访问。在您的代码中,每个线程都有局部变量max_value,并且它不识别其他线程中的变量。