Cuda 开普勒上更快的并行约化

Cuda 开普勒上更快的并行约化,cuda,reduction,kepler,Cuda,Reduction,Kepler,我只是一个CUDA初学者,试图在我的程序上使用,但我没有得到结果,下面是我正在做的一个函数,输出为0,我希望知道我的错误是什么 #ifndef __CUDACC__ #define __CUDACC__ #endif #include <cuda.h> #include <cuda_runtime.h> #include "device_launch_parameters.h" #include <iostream> #include <cuda_

我只是一个CUDA初学者,试图在我的程序上使用,但我没有得到结果,下面是我正在做的一个函数,输出为0,我希望知道我的错误是什么

#ifndef __CUDACC__  
#define __CUDACC__
#endif

#include <cuda.h>
#include <cuda_runtime.h>
#include "device_launch_parameters.h"
#include <iostream>
#include <cuda_runtime_api.h>
#include <device_functions.h>
#include <stdio.h>
#include <math.h>

__inline__ __device__
float warpReduceSum(float val) {
  for (int offset = warpSize/2; offset > 0; offset /= 2) 
    val += __shfl_down(val, offset);
  return val;
}

__inline__ __device__
float blockReduceSum(float val) {

  static __shared__ int shared[32]; // Shared mem for 32 partial sums
  int lane = threadIdx.x % warpSize;
  int wid = threadIdx.x / warpSize;

  val = warpReduceSum(val);     // Each warp performs partial reduction

  if (lane==0) shared[wid]=val; // Write reduced value to shared memory

  __syncthreads();              // Wait for all partial reductions

  //read from shared memory only if that warp existed
  val = (threadIdx.x < blockDim.x / warpSize) ? shared[lane] : 0;

  if (wid==0) val = warpReduceSum(val); //Final reduce within first warp

  return val;
}

__global__ void deviceReduceKernel(float *in, float* out, size_t N)
{
  float sum = 0;
  //reduce multiple elements per thread
  for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < N; i += blockDim.x * gridDim.x) 
  {
    sum += in[i];
  }
  sum = blockReduceSum(sum);
  if (threadIdx.x==0)
    out[blockIdx.x]=sum;
}

int main()
{
    int n = 1000000;
    float *b = new float[1]();
    float *d = new float[1]();
    float *a ;


    int blocks = (n/512)+1;
    float *d_intermediate;

    cudaMalloc((void**)&d_intermediate, n*sizeof(float));
    cudaMalloc((void**)&a, n*sizeof(float));

    cudaMemset(a, 1, n*sizeof(float));

    deviceReduceKernel<<<blocks, 512>>>(a, d_intermediate, n);
    deviceReduceKernel<<<1, 1024>>>(d_intermediate, &b[0], blocks);
    cudaMemcpy(d, b, sizeof(float), cudaMemcpyDeviceToHost);
    cudaFree(d_intermediate);
    std::cout << d[0];
    return 0;

}
\ifndef\uuu CUDACC\uu
#定义CUDACC__
#恩迪夫
#包括
#包括
#包括“设备启动参数.h”
#包括
#包括
#包括
#包括
#包括
__内联设备__
浮动值(浮动值){
对于(int offset=warpSize/2;offset>0;offset/=2)
val+=\uuuu shfl\u向下(val,偏移量);
返回val;
}
__内联设备__
浮动块还原值(浮动值){
静态_ushared _uuint shared[32];//32部分和的共享内存
int lane=螺纹内径x.x%翘曲尺寸;
int wid=螺纹IDX.x/warpSize;
val=warpReduceSum(val);//每个warp执行部分缩减
如果(lane==0)共享[wid]=val;//将减少的值写入共享内存
__syncthreads();//等待所有部分缩减
//仅当存在扭曲时才从共享内存读取
val=(threadIdx.xstd::cout您的代码存在各种问题:

  • 任何时候,当您在使用CUDA代码时遇到问题,在请求他人帮助之前,您应该使用
    CUDA memcheck
    并运行您的代码。即使您不理解错误输出,它也会对试图帮助您的其他人有用。如果您使用此代码这样做,您将收到各种错误/问题的通知

  • 传递到CUDA内核的任何指针都应该是有效的CUDA设备指针。您的
    b
    指针是主机指针:

    float *b = new float[1]();
    
    所以你不能在这里使用它:

    deviceReduceKernel<<<1, 1024>>>(d_intermediate, &b[0], blocks);
                                                     ^
    
    在这种情况下,
    b
    d
    都是主机指针。这不会将数据从设备复制到主机

  • 这可能与您的想法不符:

    cudaMemset(a, 1, n*sizeof(float));
    
    我想你认为这会用数量1填充一个
    float
    数组,但它不会。
    cudaMemset
    ,就像
    memset
    ,填充字节并取一个字节数量。如果你用它填充
    float
    数组,你实际上是在创建一个填充
    0x01010101
    的数组。我不知道是什么当您将位模式转换为
    float
    数量时转换为的hat值,但它不会为您提供
    float
    值1。我们将通过使用循环填充普通主机阵列,然后将该数据传输到要减少的设备来解决此问题

  • 下面是一段经过修改的代码,它解决了上述问题,并为我正确运行:

    $ cat t1290.cu
    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    
    __inline__ __device__
    float warpReduceSum(float val) {
      for (int offset = warpSize/2; offset > 0; offset /= 2)
        val += __shfl_down(val, offset);
      return val;
    }
    
    __inline__ __device__
    float blockReduceSum(float val) {
    
      static __shared__ int shared[32]; // Shared mem for 32 partial sums
      int lane = threadIdx.x % warpSize;
      int wid = threadIdx.x / warpSize;
    
      val = warpReduceSum(val);     // Each warp performs partial reduction
    
      if (lane==0) shared[wid]=val; // Write reduced value to shared memory
    
      __syncthreads();              // Wait for all partial reductions
    
      //read from shared memory only if that warp existed
      val = (threadIdx.x < blockDim.x / warpSize) ? shared[lane] : 0;
    
      if (wid==0) val = warpReduceSum(val); //Final reduce within first warp
    
      return val;
    }
    
    __global__ void deviceReduceKernel(float *in, float* out, size_t N)
    {
      float sum = 0;
      //reduce multiple elements per thread
      for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < N; i += blockDim.x * gridDim.x)
      {
        sum += in[i];
      }
      sum = blockReduceSum(sum);
      if (threadIdx.x==0)
        out[blockIdx.x]=sum;
    }
    
    int main()
    {
            int n = 1000000;
            float b;
            float *a, *a_host;
            a_host = new float[n];
    
            int blocks = (n/512)+1;
            float *d_intermediate;
    
            cudaMalloc((void**)&d_intermediate, blocks*sizeof(float));
            cudaMalloc((void**)&a, n*sizeof(float));
            for (int i = 0; i < n; i++) a_host[i] = 1;
            cudaMemcpy(a, a_host, n*sizeof(float), cudaMemcpyHostToDevice);
    
            deviceReduceKernel<<<blocks, 512>>>(a, d_intermediate, n);
            deviceReduceKernel<<<1, 1024>>>(d_intermediate, a, blocks);
            cudaMemcpy(&b, a, sizeof(float), cudaMemcpyDeviceToHost);
            cudaFree(d_intermediate);
            std::cout << b << std::endl;
            return 0;
    }
    $ nvcc -arch=sm_35 -o t1290 t1290.cu
    $ cuda-memcheck ./t1290
    ========= CUDA-MEMCHECK
    1e+06
    ========= ERROR SUMMARY: 0 errors
    $
    
    $cat t1290.cu
    #包括
    #包括
    #包括
    __内联设备__
    浮动值(浮动值){
    对于(int offset=warpSize/2;offset>0;offset/=2)
    val+=\uuuu shfl\u向下(val,偏移量);
    返回val;
    }
    __内联设备__
    浮动块还原值(浮动值){
    静态_ushared _uuint shared[32];//32部分和的共享内存
    int lane=螺纹内径x.x%翘曲尺寸;
    int wid=螺纹IDX.x/warpSize;
    val=warpReduceSum(val);//每个warp执行部分缩减
    如果(lane==0)共享[wid]=val;//将减少的值写入共享内存
    __syncthreads();//等待所有部分缩减
    //仅当存在扭曲时才从共享内存读取
    val=(threadIdx.xstd::cout您的代码存在各种问题:

  • 任何时候,当您在使用CUDA代码时遇到问题,在请求他人帮助之前,您应该使用
    CUDA memcheck
    并运行您的代码。即使您不理解错误输出,它也会对试图帮助您的其他人有用。如果您使用此代码这样做,您将收到各种错误/问题的通知

  • 传递到CUDA内核的任何指针都应该是有效的CUDA设备指针。您的
    b
    指针是主机指针:

    float *b = new float[1]();
    
    所以你不能在这里使用它:

    deviceReduceKernel<<<1, 1024>>>(d_intermediate, &b[0], blocks);
                                                     ^
    
    在这种情况下,
    b
    d
    都是主机指针。这不会将数据从设备复制到主机