2013-05-19 7 views
1

Обновление!Умножение матрицы Cuda дает неправильный ответ

Мой текущий код не проверяет доступ к памяти за пределами границ. Когда я запускаю cuda memcheck, он говорит, что доступ к памяти плох даже для матриц всего 2 на 2! Я получаю доступ к памяти, где я не должен так или иначе, и это проблема!

Для проверки отказа доступа оценки памяти, запустите Cuda-MemCheck ./(insert исполняемый здесь)

Ниже показан мой код для самого матричного умножения:

dim3 block(32,32); 
dim3 grid((n+31)/32, (n+31)/32); 
matrixMul<<<grid,block>>>(d_C, d_A, d_B, n, k); 

кА и kB - это матрицы со значениями в них (все они облегчают задачу).

м, п, к, все то же самое число моих квадратных матриц

кКла матрица для хранения ответа.

#ifndef _MATRIXMUL_KERNEL_H_ 
#define _MATRIXMUL_KERNEL_H_ 

#include <stdio.h> 

__global__ void matrixMul(float *kC, float *kA, float *kB, int n, int k) 
{ 

    int tx = blockIdx.x * 32 + threadIdx.x; 
    int ty = blockIdx.y * 32 + threadIdx.y; 
    float value = 0; 

    for (int i=0;i<n;i++) 
    { 
     float elementA=kA[ty*n+i]; 
     float elementB=kB[i*k+tx]; 
     value += elementA*elementB; 
    } 

    kC[ty*n+tx] = value; 
} 

#endif // #ifndef _MATRIXMUL_KERNEL_H_ 
+0

У меня просто закончилась память или еще что-то? – Mechy

+0

Где определение переменной 'значение'? Вы инициализируете его до нуля до цикла for? Этот код не похож на компиляцию. –

+0

@Robert Crovella мой плохой, я написал неправильное имя переменной, когда я переместил код. Это должно быть «float value», а не «float storage». Однако у меня есть «float value» в моей программе. Как вы думаете, это может быть моя память, если она работает до 10x10? После 10x10 значения удваиваются для некоторых строк матрицы или иногда что-то еще ... – Mechy

ответ

2

На основании того, как вы определяете сетку нитей, вы должны добавить проверку потоков в коде ядра, как это:

#ifndef _MATRIXMUL_KERNEL_H_ 
#define _MATRIXMUL_KERNEL_H_ 

#include <stdio.h> 

__global__ void matrixMul(float *kC, float *kA, float *kB, int n, int k) 
{ 

    int tx = blockIdx.x * 32 + threadIdx.x; 
    int ty = blockIdx.y * 32 + threadIdx.y; 

    if ((ty < n) && (tx < n)) { // add this line 
     float value = 0; 

     for (int i=0;i<n;i++) 
     { 
     float elementA=kA[ty*n+i]; 
     float elementB=kB[i*k+tx]; 
     value += elementA*elementB; 
     } 

     kC[ty*n+tx] = value; 
    } // add this line 
} 

#endif // #ifndef _MATRIXMUL_KERNEL_H_ 

В противном случае темы выходит за пределы допустимого массива массива будет коррумпированной ваши результаты. Вещи работают для кратных 32x32, потому что нет недопустимых потоков. В этом случае вы запускаете точно необходимое количество потоков. Но в других случаях вы запускаете дополнительные потоки. Эти дополнительные потоки, если разрешено вычислять недопустимую позицию матрицы, повредят результаты.

+0

Вау, это все исправлено. Я ценю это. Таким образом, в основном, что происходит, это то, что потоки инициализируются на основе моего вызова ядра и выполняются, даже если они вне пределов без этого утверждения if? – Mechy

+0

Да, вы определяете размер сетки с помощью вызова ядра. Когда ядро ​​запускается с этой сетью, все эти потоки запустится и в какой-то момент начнут выполнять код потока (код ядра). –

Смежные вопросы