Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/79.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
C++ 使用CUDA在GPU之间复制大数据_C++_C_Cuda - Fatal编程技术网

C++ 使用CUDA在GPU之间复制大数据

C++ 使用CUDA在GPU之间复制大数据,c++,c,cuda,C++,C,Cuda,我是CUDA的新手,我自己正在尝试一项非常简单的任务——将内存复制到图形卡,然后再复制回来。下面是我编写的代码的简化版本 常数int arraySize=100; int*data1=NULL; int*data2=NULL; //初始化了数据1和数据2 // ... int*dev_data1=NULL; int*dev_data2=NULL; //初始化了dev_数据1和dev_数据2 // ... //将数据1复制到设备 cudaMemcpydev_data1,data1,arrayS

我是CUDA的新手,我自己正在尝试一项非常简单的任务——将内存复制到图形卡,然后再复制回来。下面是我编写的代码的简化版本

常数int arraySize=100; int*data1=NULL; int*data2=NULL; //初始化了数据1和数据2 // ... int*dev_data1=NULL; int*dev_data2=NULL; //初始化了dev_数据1和dev_数据2 // ... //将数据1复制到设备 cudaMemcpydev_data1,data1,arraySize*sizeofint,cudamemcpyhostto设备; //使用gpu将dev_数据1复制到dev_数据2 gpuCopy开发数据1、开发数据2; //将dev_data2复制到数据 cudaMemcpydata2,开发数据2,阵列化*sizeofint,cudaMemcpyDeviceToHost; gpuGopy如下所示:

__全局无效gpucopy int*src,int*dst { int i=threadIdx.x; dst[i]=src[i]; }
我发现如果arraySize很小,上面的函数就可以工作。但如果arraySize达到特定大小,data2将变为全零。我的猜测是,在运行gpu功能时存在某种限制。但有办法找到答案吗?如果我有一个非常大的阵列,我如何将它复制到GPU并返回

首先你应该做的是

其次,您可能会觉得threadIdx.x提供了一个全局唯一的线程ID,但事实并非如此

因此,从以下位置修改内核行:

int i = threadIdx.x;
致:

最后,根据GPU,每个块的线程数参数不能超过512或1024。我们通过指定“每个块的线程数”和“每个网格的块数”参数来启动更大的网格:

#define nTPB 512
gpuCopy<<<(arraySize + nTPB - 1)/nTPB, nTPB>>>( dev_data1, dev_data2 ); 
结合这种网格大小调整方法,我们通常在内核中包含线程检查,以防止对任意网格/问题大小的越界访问:

__global__ void gpucopy( int* src, int* dst, int size )
{
    int i = threadIdx.x + blockDim.x * blockIdx.x;
    if (i < size)
      dst[i] = src[i];
}
同样,我们必须告诉内核问题的大小:

gpuCopy<<<(arraySize + nTPB - 1)/nTPB, nTPB>>>( dev_data1, dev_data2, arraySize ); 

您可能想首先回顾一下您应该做的事情

其次,您可能会觉得threadIdx.x提供了一个全局唯一的线程ID,但事实并非如此

因此,从以下位置修改内核行:

int i = threadIdx.x;
致:

最后,根据GPU,每个块的线程数参数不能超过512或1024。我们通过指定“每个块的线程数”和“每个网格的块数”参数来启动更大的网格:

#define nTPB 512
gpuCopy<<<(arraySize + nTPB - 1)/nTPB, nTPB>>>( dev_data1, dev_data2 ); 
结合这种网格大小调整方法,我们通常在内核中包含线程检查,以防止对任意网格/问题大小的越界访问:

__global__ void gpucopy( int* src, int* dst, int size )
{
    int i = threadIdx.x + blockDim.x * blockIdx.x;
    if (i < size)
      dst[i] = src[i];
}
同样,我们必须告诉内核问题的大小:

gpuCopy<<<(arraySize + nTPB - 1)/nTPB, nTPB>>>( dev_data1, dev_data2, arraySize ); 
您可能需要查看

threadIdx索引取决于体系结构,不能随意设置

以下代码在我的系统上一直工作到arraySize==1024,但在arraySize==1025时,我得到了未定义的值

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <iostream>
using namespace std;

__global__ void gpucopy( int* src, int* dst )
{
  int i = threadIdx.x;
  dst[i] = src[i];
} 

int main()
{
  const int arraySize = 500; // >= 1025 will fail on my system!

  int* data1 = new int[arraySize]; 
  int* data2 = new int[arraySize];
  // Initialized both data1 and data2
  // ... 
  for(int i=0; i<arraySize; i++)
    data1[i] = 2*i;

  int* dev_data1 = NULL; 
  int* dev_data2 = NULL; 
  // Initialized both dev_data1 and dev_data2
  // ... 
  cudaMalloc(&dev_data1, arraySize*sizeof(int));
  cudaMalloc(&dev_data2, arraySize*sizeof(int));

  // copy data1 to device
  cudaMemcpy(dev_data1, data1, arraySize*sizeof(int), cudaMemcpyHostToDevice );

  // copy dev_data1 to dev_data2 with gpu
  gpucopy<<<1, arraySize>>>( dev_data1, dev_data2 ); 

  // copy dev_data2 to data
  cudaMemcpy(data2, dev_data2, arraySize*sizeof(int), cudaMemcpyDeviceToHost );


  for(int i=0; i<arraySize; i++)
    if(data2[i] != data1[i])
      cout << "Error: data is different - data2[" << i << "] is " << data2[i] << endl;

      return 0;
}
您可以通过查看文档或使用deviceQuery函数找到该值

threadIdx索引依赖于体系结构,您不能随意设置它

以下代码在我的系统上一直工作到arraySize==1024,但在arraySize==1025时,我得到了未定义的值

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <iostream>
using namespace std;

__global__ void gpucopy( int* src, int* dst )
{
  int i = threadIdx.x;
  dst[i] = src[i];
} 

int main()
{
  const int arraySize = 500; // >= 1025 will fail on my system!

  int* data1 = new int[arraySize]; 
  int* data2 = new int[arraySize];
  // Initialized both data1 and data2
  // ... 
  for(int i=0; i<arraySize; i++)
    data1[i] = 2*i;

  int* dev_data1 = NULL; 
  int* dev_data2 = NULL; 
  // Initialized both dev_data1 and dev_data2
  // ... 
  cudaMalloc(&dev_data1, arraySize*sizeof(int));
  cudaMalloc(&dev_data2, arraySize*sizeof(int));

  // copy data1 to device
  cudaMemcpy(dev_data1, data1, arraySize*sizeof(int), cudaMemcpyHostToDevice );

  // copy dev_data1 to dev_data2 with gpu
  gpucopy<<<1, arraySize>>>( dev_data1, dev_data2 ); 

  // copy dev_data2 to data
  cudaMemcpy(data2, dev_data2, arraySize*sizeof(int), cudaMemcpyDeviceToHost );


  for(int i=0; i<arraySize; i++)
    if(data2[i] != data1[i])
      cout << "Error: data is different - data2[" << i << "] is " << data2[i] << endl;

      return 0;
}
您可以通过查看文档或使用deviceQuery函数找到该值


请发布完整的可编译样本!对于您发布的代码片段,它不可能帮助您解决有关0的问题。另外,请您知道具体尺寸有多大?@maxywb。刚刚在我的机器上测试过。具体尺寸为512。但是根据下面的答案,这个数字应该在不同的机器上有所不同。发布的代码可能会出现内核启动故障,导致arraySize在513及以上或1025及以上的版本没有修改输出,具体取决于传递的特定GPU和编译命令。请发布完整的可编译示例!对于您发布的代码片段,它不可能帮助您解决有关0的问题。另外,请您知道具体尺寸有多大?@maxywb。刚刚在我的机器上测试过。具体尺寸为512。但是根据下面的答案,这个数字应该在不同的机器上有所不同。发布的代码可能会出现内核启动失败,导致arraySize在513及以上或1025及以上没有修改的输出,具体取决于传递的特定GPU和编译命令。我想你的内核调用会出错,因为根据计算能力的不同,每个块最多只能启动1024个线程。当你进行usw错误检查时,你会看到这一点。没错,事实上,我只能用我认为你的内核调用来启动它,因为根据计算能力,每个块最多只能启动1024个线程。当你检查usw错误时,你会看到。没错,事实上我只能用