在CUDA中分配设备变量时出现问题

在CUDA中分配设备变量时出现问题,cuda,Cuda,尝试为设备变量赋值,然后将其复制到主机变量时遇到问题 我从d_检验开始,h_检验=0.0。我有一个简单的内核将设备变量d_test设置为1.0。然后将其复制到宿主变量h_test并打印。问题是当我打印时,我得到h_test=0.0。我做错了什么?代码如下: // -*- mode: C -*- #include <stdio.h> #include <stdlib.h> #include <cuda_runtime.h> // device variable

尝试为设备变量赋值,然后将其复制到主机变量时遇到问题

我从d_检验开始,h_检验=0.0。我有一个简单的内核将设备变量d_test设置为1.0。然后将其复制到宿主变量h_test并打印。问题是当我打印时,我得到h_test=0.0。我做错了什么?代码如下:

// -*- mode: C -*-
#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>

// device variable and kernel
__device__ float d_test;
__global__ void kernel1(float d_test) { d_test = 1.0; }


int main() {

  // initialise variables
  float h_test = 0.0;
  cudaMemset(&d_test,0,sizeof(float));

  // invoke kernel
  kernel1 <<<1,1>>> (d_test);

  // Copy device variable to host and print
  cudaMemcpy(&h_test,&d_test,sizeof(float),cudaMemcpyDeviceToHost);
  printf("%f\n",h_test);  

}
/-*-模式:C-*-
#包括
#包括
#包括
//设备变量与内核
__装置浮球试验;
__全局无效内核1(浮点d_测试){d_测试=1.0;}
int main(){
//初始化变量
浮球h_试验=0.0;
cudaMemset(&d_测试,0,sizeof(float));
//调用内核
核1(d_检验);
//将设备变量复制到主机并打印
cudaMemcpy(h_测试、d_测试、sizeof(float)、cudamemcpydevicetoost);
printf(“%f\n”,h_测试);
}

我猜kernel1会更改其参数d_test,因为它隐藏了全局设备变量。
重命名其中一个,或者如果这适用于CUDA,则通过设置::d_test显式使用全局范围。

您的代码有几个问题

  • 正如pezcode正确指出的那样,
    kernel1
    的参数
    d_test
    隐藏了全局变量,因此当它赋值给
    d_test
    时,它实际上是在更改其参数的值,而不是您想要的全局变量<在本例中,code>kernel1不需要使用参数

  • 从全局
    \uuu设备\uuu
    变量复制时,请使用
    cudaMemcpyFromSymbol
    而不是
    cudaMemcpy

  • 以下是完整的解决方案:

    // -*- mode: C -*-
    #include <stdio.h>
    #include <stdlib.h>
    #include <cuda_runtime.h>
    
    // device variable and kernel
    __device__ float d_test;
    __global__ void kernel1() { d_test = 1.0; }
    
    int main() {
    
      // initialise variables
      float h_test = 0.0;
      cudaMemset(&d_test,0,sizeof(float));
    
      // invoke kernel
      kernel1 <<<1,1>>> ();
    
      // Copy device variable to host and print
      cudaMemcpyFromSymbol(&h_test, d_test, sizeof(float), 0, cudaMemcpyDeviceToHost);
      // or cudaMemcpyFromSymbol(&h_test, "d_test", sizeof(float), 0, cudaMemcpyDeviceToHost);
      // until CUDA 5.0
      printf("%f\n",h_test);  
    }
    
    2019年11月更新


    声明“CUDA 4.1中不推荐使用将变量命名为符号参数的字符串,CUDA 5.0中删除了该字符串。”

    cudaMemcpyFromSymbol在与cudaMemcpy抗争了很长一段时间并取回了错误的值后对我起到了作用。我不得不删除“d_test”周围的引号,并在cudaMemset中得到了一个无效的参数错误,所以只使用了代码中以前的cudamaloc。

    这段代码对我来说很好。钥匙在那儿

    第二个变量应该是这样的\n

    cudaMemcpyFromSymbol(&h_测试、d_测试、sizeof(float)、0、cudaMemcpyDeviceToHost)

    然后用

    nvcc-Xcompiler-arch=sm_30 sample.cu-o sample.exe

    我已将d_test的名称更改为内核中的test,但这没有任何区别。全局范围是什么:dxTestTygy?出于某种原因,我认为您正在使用C++,在这里您可以使用范围:var访问特定范围内的变量。仅仅使用::就意味着全局作用域,从而访问由同名函数参数隐藏的全局变量。抱歉造成混淆:在cudaMemcpyFromSymbol中使用quote会在复制操作后导致0.0,因此只需删除quote符号即可。您使用的CUDA版本是什么?此时,
    cudaMemset
    返回错误消息:“cudaMemset”;和
    cudaMemcpyFromSymbol
    返回错误消息:“返回错误消息”(API已更改,请参阅:)不确定确切原因,但一旦删除引号(例如cudaMemcpyFromSymbol(&h_测试,“d_测试”,sizeof(float),0,cudaMemcpyDeviceToHost);)
    $ nvcc test.cu -run
    1.000000