2014-09-06 3 views
7

Wenn ich dieses Programm ausführen bekomme ich "ein illegaler Speicherzugriff wurde in MatrixMulti.cu bei Zeile 48 aufgetreten" Fehler. Ich habe viel gesucht und versucht. Ich hoffe also, dass mir jemand helfen kann.Einfache CUDA-Test schlägt immer mit "ein unzulässiger Speicherzugriff wurde aufgetreten" Fehler

Zeile 48: HANDLE_ERROR (cudaMemcpy (Array, devarray, N * N * sizeof (int), cudaMemcpyDeviceToHost));

Das Programm ist nur in CUDA zu bekommen. Ich habe versucht, eine Matrixmultiplikation zu implementieren.

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

Antwort

9

Im Allgemeinen funktioniert Ihre Methode zum Zuweisen und Kopieren eines doppelt subskribierten C-Arrays nicht. cudaMemcpy erwartet flach, zusammenhängend zugeordnet, Einzel-Pointer, Single-Subscript-Arrays.

Als Ergebnis dieser Verwirrung, wobei die Zeiger auf den Kernel übergeben (int** a, int** b) (sicher) nicht richtig sein kann dereferenced zweimal:

b[0][0]=4; 

Wenn Sie versuchen, die oben im Kernel-Code zu tun, Sie bekommen einen unzulässigen Speicherzugriff, da Sie auf dem Gerät keine Zuordnung von Zeiger zu Zeiger zugewiesen haben.

Wenn Sie Ihren Code mit cuda-memcheck ausführen, erhalten Sie einen weiteren Hinweis auf den unzulässigen Speicherzugriff im Kernel-Code.

Der übliche Vorschlag in diesen Fällen besteht darin, Ihre 2D-Arrays auf eine einzelne Dimension zu reduzieren und entsprechende Zeiger- oder Indexarithmetik zu verwenden, um 2D-Zugriff zu simulieren. Es ist möglich, 2D-Arrays (d. H. Doppel-Index, Doppel-Zeiger) zuzuordnen, aber es ist ziemlich beteiligt (teilweise aufgrund der Notwendigkeit für eine "tiefe Kopie"). Wenn Sie mehr darüber erfahren möchten, suchen Sie einfach in der oberen rechten Ecke nach CUDA 2D array.

Hier ist eine Version des Codes ist, die das Array für die geräteseitige Anordnung Abflachung hat:

$ 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

Danke :) Ich denke, ich werde die 1D-Version der Matrix versuchen, so scheint es leichter zu sein, – Henrik

Verwandte Themen