Thrust::sort 使无效参数崩溃

Thrust::sort crashes invalid argument

我正尝试在设备内存上使用 thrust::sort。但它在运行时崩溃。 我也试过禁用调试信息生成。

这是一个最小的例子:

cudaSetDevice(0);
int u[10];
int* v;
cudaMalloc(&v, 10 * sizeof(int));
for (int i = 0; i < 10 ; i++)
    u[i] = 10-i;
cudaMemcpy(u, v, 10 * sizeof(int), cudaMemcpyHostToDevice);
try{
    thrust::sort(thrust::device_ptr<int>(v), thrust::device_ptr<int>(v+10));
}
catch (thrust::system_error &e)
    printf("Error: %s \n",e.what());
cudaMemcpy(v, u, 10 * sizeof(int), cudaMemcpyDeviceToHost);
for (int i = 0; i < 10; i++)
    printf("%d\n", u[i]);

e.what() 给出以下信息:

CUDA error 11 [c:\program files\nvidia gpu computing toolkit\cuda\v7.5\include\thrust\system\cuda\detail\cub\device\disp atch/device_radix_sort_dispatch.cuh, 687]: invalid argument CUDA error 11 [c:\program files\nvidia gpu computing toolkit\cuda\v7.5\include\thrust\system\cuda\detail\cub\device\disp atch/device_radix_sort_dispatch.cuh, 875]: invalid argument Error: after cub_::DeviceRadixSort::SortKeys(1): invalid argument

我正在使用带有 Cuda 助手的 GeForce 940M 和 VS13 来生成项目。 nvcc 构建行是:

"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\bin\nvcc.exe" -gencode=arch=compute_20,code=\"sm_20,compute_20\" --use-local-env --cl-version 2013 -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include" --keep-dir Debug -maxrregcount=0 --machine 32 --compile -cudart static -g -DWIN32 -D_DEBUG -D_CONSOLE -D_MBCS -Xcompiler "/EHsc /W3 /nologo /Od /Zi /RTC1 /MDd " -o Debug\kernel.cu.obj "C:\Users\ndrei\Documents\Visual Studio13\Projects\Thrust_Test\Thrust_Test\kernel.cu"

请帮帮我!

首先,您的示例不完整。把头文件等砍掉有什么好处呢?这不会让其他试图帮助您的人变得更容易。我认为这甚至不是您实际上 运行ning 的代码的摘录,因为您的 try/catch 格式不正确(编译错误)。

以后请提供合适的MCVE。它应该是一个 完整的 代码,有人可以复制、粘贴、编译和 运行,而无需添加或更改任何内容。

关于推力误差:

  1. cudaMemcpy 不是推力的一部分。它是 cuda 运行time API 的一部分,建议您在使用 cuda 运行time [=] 的代码遇到问题时使用 proper cuda error checking 84=]。如果你这样做了,而不是不知道错误在哪里,你的注意力会立即减少到一行代码。

  2. 这是错误的:

    cudaMemcpy(u, v, 10 * sizeof(int), cudaMemcpyHostToDevice);
    

    cudaMemcpymemcpy 一样,将指向复制操作的 目标 的指针作为其第一个参数,然后是指向 复制操作的来源

    由于u是主机指针而v是设备指针,这与您的意图不符(以及复制操作的规定方向,即cudaMemcpyHostToDevice) .

  3. 你在后续的cudaMemcpy操作中也犯了类似的错误。

下面是一个更好的例子MCVE。它是您显示的代码的修改版本,错误已修复:

#include <stdio.h>
#include <thrust/sort.h>
#include <thrust/device_ptr.h>
#include <thrust/system_error.h>


#define cudaCheckErrors(msg) \
    do { \
        cudaError_t __err = cudaGetLastError(); \
        if (__err != cudaSuccess) { \
            fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
                msg, cudaGetErrorString(__err), \
                __FILE__, __LINE__); \
            fprintf(stderr, "*** FAILED - ABORTING\n"); \
            exit(1); \
        } \
    } while (0)

int main(){

  cudaSetDevice(0);
  int u[10];
  int* v;
  cudaMalloc(&v, 10 * sizeof(int));
  cudaCheckErrors("cudaMalloc fail");
  for (int i = 0; i < 10 ; i++)
    u[i] = 10-i;
  cudaMemcpy(v, u, 10 * sizeof(int), cudaMemcpyHostToDevice);
  cudaCheckErrors("cudaMemcpy 1 fail");
  try{
    thrust::sort(thrust::device_ptr<int>(v), thrust::device_ptr<int>(v+10));
    }
  catch (thrust::system_error &e){
    printf("Error: %s \n",e.what());}
  cudaMemcpy(u, v, 10 * sizeof(int), cudaMemcpyDeviceToHost);
  cudaCheckErrors("cudaMemcpy 2 fail");
  for (int i = 0; i < 10; i++)
    printf("%d\n", u[i]);
}

备注:

  1. Thrust 系统错误机制 捕获预先存在的 CUDA 错误,并抛出这些错误,以及任何可能与您的实际推力代码相关的错误.因此,建议对 CUDA 代码进行 CUDA 错误检查,并对推力代码进行推力错误检查,以减少调试过程的混乱。

  2. 作为一个不相关的建议:您的项目设置为构建:

    • 一台cc2.0设备。
    • 32 位应用程序

    这些都不是推荐的设置。我会建议修改您的项目以构建一个 Release,x64 应用程序,并且我会建议从 cc2.0 修改您的构建目标以匹配您的 GPU 的计算能力。在您的项目设置中,这可能意味着将 CUDA 设备下的 Visual Studio 项目设置从 compute_20,sm_20 更改为 compute_50,sm_50 以匹配您的 GeForce 940M GPU.