C++ 简单CUDA测试总是以“失败”开头;遇到非法内存访问;错误

C++ 简单CUDA测试总是以“失败”开头;遇到非法内存访问;错误,c++,pointers,matrix,cuda,C++,Pointers,Matrix,Cuda,如果我运行这个程序,我会得到“matrixMulti.cu在第48行遇到非法内存访问”错误。我找了很多,试了很多。所以我希望有人能帮助我 第48行:句柄_错误(cudaMemcpy(数组,devarray,NNsizeof(int),cudaMemcpyDeviceToHost)) 这个项目只是为了进入CUDA。我试图实现一个矩阵乘法 #include <iostream> #include<cuda.h> #include <stdio.h> using

如果我运行这个程序,我会得到“matrixMulti.cu在第48行遇到非法内存访问”错误。我找了很多,试了很多。所以我希望有人能帮助我

第48行:句柄_错误(cudaMemcpy(数组,devarray,NNsizeof(int),cudaMemcpyDeviceToHost))

这个项目只是为了进入CUDA。我试图实现一个矩阵乘法

#include <iostream>
#include<cuda.h>
#include <stdio.h>

using namespace std;

#define HANDLE_ERROR( err ) ( HandleError( err, __FILE__, __LINE__ ) )
void printVec(int** a, int n);

static void HandleError( cudaError_t err, const char *file, int line )
{
    if (err != cudaSuccess)
    {
    printf( "%s in %s at line %d\n", cudaGetErrorString( err ),
            file, line );
    exit( EXIT_FAILURE );
    }
}

void checkCUDAError(const char *msg)
{
    cudaError_t err = cudaGetLastError();
    if( cudaSuccess != err) 
    {
        fprintf(stderr, "Cuda error: %s: %s.\n", msg, 
                              cudaGetErrorString( err) );
        exit(EXIT_FAILURE);
    }                         
}
__global__ void MatrixMulti(int** a, int** b) {
    b[0][0]=4;
}

int main() {
    int N =10;
    int** array, **devarray;
    array = new int*[N];

    for(int i = 0; i < N; i++) {
        array[i] = new int[N];  
    }
    
    HANDLE_ERROR ( cudaMalloc((void**)&devarray, N*N*sizeof(int) ) );
    HANDLE_ERROR ( cudaMemcpy(devarray, array, N*N*sizeof(int), cudaMemcpyHostToDevice) );  
    MatrixMulti<<<1,1>>>(array,devarray);
    HANDLE_ERROR ( cudaMemcpy(array, devarray, N*N*sizeof(int), cudaMemcpyDeviceToHost) );
    HANDLE_ERROR ( cudaFree(devarray) );
    printVec(array,N);

    return 0;
}

void printVec(int** a , int n) {
    for(int i =0 ; i < n; i++) {
        for ( int j = 0; j <n; j++) {
        cout<< a[i][j] <<" ";
        }       
        cout<<" "<<endl;    
    }
}
#包括
#包括
#包括
使用名称空间std;
#定义句柄错误(err)(句柄错误(err,文件,行)
无效打印向量(整数**a,整数n);
静态void HandleError(cudaError\u t err,const char*文件,int行)
{
if(err!=cudaSuccess)
{
printf(“%s在%s中的第%d行\n”,cudaGetErrorString(错误),
文件、行);
退出(退出失败);
}
}
无效检查CUDAERROR(常量字符*msg)
{
cudaError_t err=cudaGetLastError();
如果(cudaSuccess!=错误)
{
fprintf(标准,“Cuda错误:%s:%s.\n”,消息,
cudaGetErrorString(err));
退出(退出失败);
}                         
}
__全局无效矩阵多(整数**a,整数**b){
b[0][0]=4;
}
int main(){
int N=10;
整数**数组,**德瓦里;
数组=新整数*[N];
对于(int i=0;i对于(int j=0;j一般来说,分配和复制双下标C数组的方法不起作用。
cudaMemcpy
需要平面、连续分配、单指针、单下标数组

由于这种混乱,传递给内核的指针(
int**a,int**b
)无法正确(安全)地取消引用两次:

b[0][0]=4;
当您尝试在内核代码中执行上述操作时,您会获得非法内存访问,因为您没有在设备上正确分配指针到指针样式的分配

如果您使用
cuda memcheck
运行代码,您将在内核代码中得到另一个非法内存访问的指示

在这些情况下,通常建议将2D数组“展平”为一维,并使用适当的指针或索引算法来模拟2D访问。可以分配2D数组(即双下标、双指针),但这相当复杂(部分原因是需要“深拷贝”)。如果您想了解更多信息,只需在右上角搜索
CUDA 2D array

下面是一个版本的代码,其中包含设备端阵列的阵列展平:

$ cat t60.cu
#include <iostream>
#include <cuda.h>
#include <stdio.h>

using namespace std;

#define HANDLE_ERROR( err ) ( HandleError( err, __FILE__, __LINE__ ) )
void printVec(int** a, int n);

static void HandleError( cudaError_t err, const char *file, int line )
{
    if (err != cudaSuccess)
    {
    printf( "%s in %s at line %d\n", cudaGetErrorString( err ),
            file, line );
    exit( EXIT_FAILURE );
    }
}

void checkCUDAError(const char *msg)
{
    cudaError_t err = cudaGetLastError();
    if( cudaSuccess != err)
    {
        fprintf(stderr, "Cuda error: %s: %s.\n", msg,
                              cudaGetErrorString( err) );
        exit(EXIT_FAILURE);
    }
}

__global__ void MatrixMulti(int* b, unsigned n) {
    for (int row = 0; row < n; row++)
      for (int col=0; col < n; col++)
    b[(row*n)+col]=col;  //simulate 2D access in kernel code
}

int main() {
    int N =10;
    int** array, *devarray;  // flatten device-side array
    array = new int*[N];
    array[0] = new int[N*N]; // host allocation needs to be contiguous
    for (int i = 1; i < N; i++) array[i] = array[i-1]+N; //2D on top of contiguous allocation

    HANDLE_ERROR ( cudaMalloc((void**)&devarray, N*N*sizeof(int) ) );
    HANDLE_ERROR ( cudaMemcpy(devarray, array[0], N*N*sizeof(int), cudaMemcpyHostToDevice) );
    MatrixMulti<<<1,1>>>(devarray, N);
    HANDLE_ERROR ( cudaMemcpy(array[0], devarray, N*N*sizeof(int), cudaMemcpyDeviceToHost) );
    HANDLE_ERROR ( cudaFree(devarray) );
    printVec(array,N);

    return 0;
}

void printVec(int** a , int n) {
    for(int i =0 ; i < n; i++) {
        for ( int j = 0; j <n; j++) {
        cout<< a[i][j] <<" ";
        }
        cout<<" "<<endl;
    }
}
$ nvcc -arch=sm_20 -o t60 t60.cu
$ ./t60
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
$
$cat t60.cu
#包括
#包括
#包括
使用名称空间std;
#定义句柄错误(err)(句柄错误(err,文件,行)
无效打印向量(整数**a,整数n);
静态void HandleError(cudaError\u t err,const char*文件,int行)
{
if(err!=cudaSuccess)
{
printf(“%s在%s中的第%d行\n”,cudaGetErrorString(错误),
文件、行);
退出(退出失败);
}
}
无效检查CUDAERROR(常量字符*msg)
{
cudaError_t err=cudaGetLastError();
如果(cudaSuccess!=错误)
{
fprintf(标准,“Cuda错误:%s:%s.\n”,消息,
cudaGetErrorString(err));
退出(退出失败);
}
}
__全局无效矩阵multi(int*b,无符号n){
对于(int行=0;行对于(int j=0;j谢谢:)我想我会尝试矩阵的1D版本,它似乎更容易。感谢您提到
cuda memcheck
工具。它对调试非常有帮助,如果我早点发现这个工具,我可以节省几天的时间。