#c #cuda #matrix-multiplication
#c #cuda #матрица-умножение
Вопрос:
Может кто-нибудь сказать мне, что я здесь делаю не так? Я пытаюсь создать программу, которая возвращает матрицу к мощности, используя cuda. Кажется, что cudaMemcpy (ln103) не возвращает результирующий массив. Я проверяю это, возвращая первый элемент в матрице, но я всегда просто получаю 0. Может быть, что-то не так с моим ядром? Был бы признателен за любую помощь:
РЕДАКТИРОВАТЬ: я должен уточнить, ядро повторяется (начиная с матрицы, умноженной на соответствующую идентификационную матрицу, затем умножается на каждый результат впоследствии) до k раз, что приводит матрицу к степени.
т.е. A является матрицей A ^ 0 = I (единичная матрица) A ^ k = A ^(k-1)*A
ввод :
<n>
<power>
<element>
.....
код:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#define BLOCK 8
#define SIZE (BLOCK * 64)
#define TILE_SIZE (8)
int n;
float *
create_matrix_h(unsigned int w, unsigned int h) {
float *m;
m = (float *) malloc(w * h * sizeof(float));
if (m == NULL) {
fprintf(stderr, "Failed to malloc.n");
exit(1);
}
return m;
}
__global__ void
kernel3(const float *m1, const float *m2, float *m3, unsigned int width) {
const unsigned int row = blockIdx.y*blockDim.y threadIdx.y;
const unsigned int col = blockIdx.x*blockDim.x threadIdx.x;
unsigned int t, i;
float result = 0, a, b;
for (t = 0; t < width / TILE_SIZE; t) {
for (i = 0; i != TILE_SIZE; i) {
a = m1[row*width t*TILE_SIZE i];
b = m2[(t*TILE_SIZE i)*width col];
result = a * b;
}
__syncthreads();
}
m3[row*width col] = resu<
}
float *
create_matrix_d(int w, int h) {
float *m;
if (cudaMalloc(amp;m, w * h * sizeof(float)) == cudaErrorMemoryAllocation) {
fprintf(stderr, "Failed to cudaMalloc.n");
return NULL;
//exit(1);
}
return m;
}
void
fill_matrix_h(float *const m, int w, int h, float *const values, int nvalues) {
int i, j = 0;
for (i = 0; i != w * h; i) {
m[i] = values[j];
j = (j 1) % nvalues;
}
}
int
main(void) {
int k;
if (scanf("%d", amp;n) !=1 || n<1){
return 0;
}
if (scanf(" %d", amp;k) !=1 || k<0){
return 0;
}
float *hm[3], *dm[3];
dim3 bdim(TILE_SIZE, TILE_SIZE);
dim3 gdim(SIZE/TILE_SIZE, SIZE/TILE_SIZE);
int i;
for(i=0; i<3; i) {
hm[i] = create_matrix_h(SIZE, SIZE);
dm[i] = create_matrix_d(SIZE, SIZE);
}
float tem[n*n];
for(i=0; i<n*n; i) {
if (scanf(" %f", amp;tem[i]) !=1){
return 0;
}
}
float temid[n*n];
int j = 0;
for (i = 0; i != n*n; i) {
if (i==0 || i == j (n 1)) {
temid[i] = 1;
j = i;
}
else {
temid[i] = 0;
}
}
fill_matrix_h(hm[0], SIZE, SIZE, tem, sizeof(tem)/sizeof(float));
fill_matrix_h(hm[1], SIZE, SIZE, temid, sizeof(temid)/sizeof(float));
cudaMemcpy(dm[0], hm[0], SIZE*SIZE*sizeof(float), cudaMemcpyHostToDevice);
int w;
for (w=0; w<k; w) {
cudaMemcpy(dm[1], hm[1], SIZE*SIZE*sizeof(float), cudaMemcpyHostToDevice);
kernel3<<<gdim, bdim>>>(dm[0], dm[1], dm[2], SIZE);
cudaThreadSynchronize();
cudaMemcpy(hm[2], dm[2], SIZE*SIZE*sizeof(float), cudaMemcpyDeviceToHost);
hm[1] = hm[2];
}
printf(" %.3f ", hm[2][0]);
return 0;
}
спасибо за ваш ответ, Паван. Теперь, когда я запускаю его, я получаю бесконечный цикл с приведенными ниже входными данными при вызове ядра. Также новый код. Я ценю вашу помощь
2
2
1
2
3
4
новый код:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#define BLOCK 8
#define SIZE (BLOCK * 64)
#define TILE_SIZE (8)
int n;
float *
create_matrix_h(unsigned int w, unsigned int h) {
float *m;
m = (float *) malloc(w * h * sizeof(float));
if (m == NULL) {
fprintf(stderr, "Failed to malloc.n");
exit(1);
}
return m;
}
void
print_matrix(const float *m, const int w, const int h) {
int x, y;
for (y = 0; y != h; y) {
for (x = 0; x != w; x)
printf("%.03f ", m[y*w x]);
printf("n");
}
}
void
cpu_mult(const float *m1, const float *m2, float *m3, unsigned int width) {
unsigned int i, j, k;
float resu<
for (i = 0; i != width; i) {
for (j = 0; j != width; j) {
result = 0;
for (k = 0; k != width; k)
result = m1[i*width k] * m2[k*width j];
m3[i*width j] = resu<
}
}
}
__global__ void
kernel3(const float *m1, const float *m2, float *m3, unsigned int width) {
const unsigned int row = blockIdx.y*blockDim.y threadIdx.y;
const unsigned int col = blockIdx.x*blockDim.x threadIdx.x;
unsigned int t, i;
float result = 0, a, b;
for (t = 0; t < width / TILE_SIZE; t) {
for (i = 0; i != TILE_SIZE; i) {
a = m1[row*width t*TILE_SIZE i];
b = m2[(t*TILE_SIZE i)*width col];
result = a * b;
}
__syncthreads();
}
m3[row*width col] = resu<
}
float *
create_matrix_d(int w, int h) {
float *m;
if (cudaMalloc(amp;m, w * h * sizeof(float)) == cudaErrorMemoryAllocation) {
fprintf(stderr, "Failed to cudaMalloc.n");
return NULL;
//exit(1);
}
return m;
}
void
fill_matrix_h(float *const m, int w, int h, float *const values, int nvalues) {
int i, j = 0;
for (i = 0; i != w * h; i) {
m[i] = values[j];
j = (j 1) % nvalues;
}
}
int
main(void) {
int k;
if (scanf("%d", amp;n) !=1 || n<1){
return 0;
}
if (scanf(" %d", amp;k) !=1 || k<0){
return 0;
}
float *hm[3], *dm[3];
dim3 bdim(TILE_SIZE, TILE_SIZE);
dim3 gdim(SIZE/TILE_SIZE, SIZE/TILE_SIZE);
int i;
for(i=0; i<3; i) {
hm[i] = create_matrix_h(SIZE, SIZE);
dm[i] = create_matrix_d(SIZE, SIZE);
}
float tem[n*n];
for(i=0; i<n*n; i) {
if (scanf(" %f", amp;tem[i]) !=1){
return 0;
}
}
float temid[n*n];
int j = 0;
for (i = 0; i != n*n; i) {
if (i==0 || j == n) { // not j (n 1)
temid[i] = 1;
j=0;
}
else {
temid[i] = 0;
j ;
}
}
fill_matrix_h(hm[0], SIZE, SIZE, tem, sizeof(tem)/sizeof(float));
fill_matrix_h(hm[1], SIZE, SIZE, temid, sizeof(temid)/sizeof(float));
cudaMemcpy(dm[0], hm[0], SIZE*SIZE*sizeof(float), cudaMemcpyHostToDevice);
dm[1] = dm[0]; // For the first iteration Result = A * A;
int w;
if (k==0) {
hm[2] = hm[1];
}
else if (k==1) {
hm[2] = hm[0];
}
else {
for (w=1; w<k; w) {
kernel3<<<gdim, bdim>>>(dm[0], dm[1], dm[2], SIZE);
cudaThreadSynchronize();
// No need to copy back to host
// cudaMemcpy(hm[2], dm[2], SIZE*SIZE*sizeof(float), cudaMemcpyDeviceToHost);
// Copy between device pointers
cudaMemcpy(dm[1], dm[2], SIZE*SIZE*sizeof(float), cudaMemcpyDeviceToDevice);
}
cudaMemcpy(hm[2], dm[1], SIZE*SIZE*sizeof(float), cudaMemcpyDeviceToHost);
}
print_matrix(hm[2], n, n);
return 0;
}
Комментарии:
1. если это домашнее задание или курсовая работа, вам действительно следует пометить ее как таковую. Здесь широко расходятся мнения о том, допустимы ли вопросы домашнего задания в stackoverflow.
2. спасибо, я запомню это на будущее
Ответ №1:
Я полагаю, что здесь мы находимся на одном курсе. (comp2129). В ответ на ваш бесконечный цикл размер вашего блока / плитки слишком мал. Установите для вашего блока значение 16 и повторите попытку. Я получаю ошибки seg, хотя D:.
Комментарии:
1. ха-ха! да, я думаю, что довольно много людей чувствуют нашу боль, на странице отправки есть море красного. Ну что ж, теперь есть о чем беспокоиться.
Ответ №2:
Вы неправильно создаете идентификационную матрицу.
for (i = 0; i != n*n; i) {
if (i==0 || i == j (n)) { // not j (n 1)
temid[i] = 1;
j = i;
}
else {
temid[i] = 0;
}
}
На самом деле вам не нужно умножать на единичную матрицу, поскольку вы знаете, что результатом всегда будут входные данные.
Измените это
fill_matrix_h(hm[0], SIZE, SIZE, tem, sizeof(tem)/sizeof(float));
fill_matrix_h(hm[1], SIZE, SIZE, temid, sizeof(temid)/sizeof(float));
cudaMemcpy(dm[0], hm[0], SIZE*SIZE*sizeof(float), cudaMemcpyHostToDevice);
int w;
for (w=0; w<k; w) {
cudaMemcpy(dm[1], hm[1], SIZE*SIZE*sizeof(float), cudaMemcpyHostToDevice);
kernel3<<<gdim, bdim>>>(dm[0], dm[1], dm[2], SIZE);
cudaThreadSynchronize();
cudaMemcpy(hm[2], dm[2], SIZE*SIZE*sizeof(float), cudaMemcpyDeviceToHost);
hm[1] = hm[2];
}
Для
fill_matrix_h(hm[0], SIZE, SIZE, tem, sizeof(tem)/sizeof(float));
cudaMemcpy(dm[0], hm[0], SIZE*SIZE*sizeof(float), cudaMemcpyHostToDevice);
dm[1] = dm[0]; // For the first iteration Result = A * A;
int w;
for (w=0; w<k; w) {
kernel3<<<gdim, bdim>>>(dm[0], dm[1], dm[2], SIZE);
cudaThreadSynchronize();
// No need to copy back to host
// cudaMemcpy(hm[2], dm[2], SIZE*SIZE*sizeof(float), cudaMemcpyDeviceToHost);
// Copy between device pointers
cudaMemcpy(dm[1], dm[2], SIZE*SIZE*sizeof(float), cudaMemcpyDeviceToDevice);
}
Комментарии:
1. Привет, не могли бы вы прокомментировать, что вы подразумеваете под бесконечным циклом? Как вывести значение W в начале каждого цикла?
2. Привет. Хм, может быть, это не цикл, когда я запускаю в gdb, он просто говорит «[Новый поток 0x7ffff778b700 (LWP 9650)]» «[Новый поток 0x7ffff778a700 (LWP 9651)]» и т. Д
3. предположительно до 64, где оно просто останавливается