2014-09-06 14 views
7

Nếu tôi chạy chương trình này, tôi gặp phải lỗi "truy cập bộ nhớ không hợp lệ trong ma trậnMulti.cu tại dòng 48". Tôi đã tìm kiếm và thử rất nhiều. Vì vậy, tôi hy vọng ai đó có thể giúp tôi.Kiểm tra CUDA đơn giản luôn không thành công với lỗi "truy cập bộ nhớ bất hợp pháp"

Dòng 48: HANDLE_ERROR (cudaMemcpy (mảng, devarray, N * N * sizeof (int), cudaMemcpyDeviceToHost));

Chương trình chỉ để tham gia vào CUDA. Tôi đã cố gắng để thực hiện một phép nhân ma trận.

#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;  
    } 
} 

Trả lời

9

Nói chung, phương pháp phân bổ và sao chép mảng C được lập chỉ mục kép sẽ không hoạt động. cudaMemcpy mong đợi phẳng, được phân bổ liên tiếp, các mảng đơn, con trỏ đơn.

Như một kết quả của sự nhầm lẫn này, các con trỏ được truyền cho kernel (int** a, int** b) không thể đúng cách (một cách an toàn) dereferenced hai lần:

b[0][0]=4; 

Khi bạn cố gắng làm các việc trên trong mã hạt nhân, bạn sẽ có được truy cập bộ nhớ bất hợp pháp, bởi vì bạn đã không phân bổ đúng cách phân bổ kiểu con trỏ tới con trỏ trên thiết bị.

Nếu bạn chạy mã của mình với cuda-memcheck, bạn sẽ nhận được một dấu hiệu khác về việc truy cập bộ nhớ bất hợp pháp trong mã hạt nhân.

Đề xuất thông thường trong những trường hợp này là "làm phẳng" mảng 2D của bạn thành một chiều và sử dụng số học hoặc chỉ số thích hợp để mô phỏng truy cập 2D. Nó là có thể để phân bổ mảng 2D (tức là double-subscript, double-pointer), nhưng nó là khá tham gia (một phần do sự cần thiết cho một "bản sao sâu"). Nếu bạn muốn tìm hiểu thêm về điều đó, chỉ cần tìm kiếm ở góc trên bên phải cho CUDA 2D array.

Dưới đây là một phiên bản của mã của bạn có các mảng phẳng cho mảng thiết bị-side:

$ 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 
$ 
+0

Cảm ơn bạn :) Tôi nghĩ rằng tôi sẽ thử phiên bản 1D của ma trận, nó có vẻ là dễ dàng hơn – Henrik

Các vấn đề liên quan