host
и tran
должны быть выделены и инициализированы перед их использованием.Например, в C вы будете использовать malloc
и free
, проверяя возвращаемые значения в случае ошибок выделения:
// for strerror
#include <string.h>
...
int iobufsize(width) {
return 128*width*sizeof(float);
}
float** alloc_matrix(...) {
float **matrix, *pool;
int i, eno=0;
// allocate array of array pointers
if ((matrix = (float**)malloc( ... ))) {
/* Allocate array to hold data. This array will be divided up to
create the arrays used in the matrix. Alternatively, each matrix array
could be allocated separately.
*/
if ((pool = (float*) malloc( ... ))) {
for (i=0; i < ... ; i++) {
// each item in matrix points to a subarray of the data array
matrix[i] = pool + i * ...;
}
} else {
/* free() shouldn't change errno, but this isn't guaranteed
for every implementation, so save errno to be safe.
*/
eno = errno;
free(matrix);
errno = eno;
matrix = NULL;
}
}
return matrix;
}
void free_matrix(float **matrix, ...) {
if (matrix) {
free(*matrix);
free(matrix);
}
}
void load() {
float* host;
float** tran;
int width = 600;
int size = iobufsize(width);
if ((host = (float*)malloc(size))) {
if ((tran = alloc_matrix( ... ))) {
// initialize 'host' buffer somehow
...
printf("testing\n");
transpose(host, tran, width);
printf("testing 3\n");
printf(" value =%d \n", tran[0][0]);
printf("done\n");
free_matrix(tran, ...);
free(host);
} else {
/* Note: strerror isn't thread safe. If load() is run concurrently,
make use of strerror_r instead.
*/
fprintf(stderr, "Couldn't allocate output buffer: %s.\n", strerror(errno));
free(host);
}
} else {
fprintf(stderr, "Couldn't allocate input buffer: %s.\n", strerror(errno));
}
}
В качестве улучшения вы можете связать матрицу (массивуказателей массива) в структуру вместе с размерами матрицы.Это шаг к созданию класса матрицы.
В C ++ вы будете использовать new[]
и delete[]
, создавать классы для host
и tran
, которые будут членами другого класса, которыйуправляет взаимодействием.Это упрощает управление памятью (особенно всякий раз, когда new[]
выдает bad_alloc
), потому что вы можете применить шаблон RAII .
Существует довольно много других проблем с вашимкод.Когда вы выделяете (например, с cudaMalloc
) или копируете (например, с cudaMemcpy
) память, семантика (например, семантика указателя) не применяется к содержимому.Это имеет ряд последствий в вашем коде.С одной стороны, каждое распределение может дать вам только одномерный массив.Если вам нужны массивы более высокого размера, вы должны выделить массивы указателей для массивов меньшего размера, выделить массивы меньшего размера, а затем установить указатели в массиве более высокого измерения так, чтобы они указывали на массивы меньшего размера (как указано в alloc_matrix
).Например, cudaMalloc(&GPU_output, size);
создает одномерный массив float**
, но не инициализирует содержимое.В результате у вас нет действительного массива указателей массива.
Кроме того, размер GPU_output
неправильный;size
- это общий размер данных, а не размер для многомерного массива.Эта ошибка возникает из-за обработки 1 и 2-х мерных массивов одинаковоони не.1-мерный массив - это непрерывная область памяти, где содержимое представляет собой последовательность объектов, которые имеют одинаковое расположение (т. Е. Элементы массива являются однородными).2-мерный массив - это массив указателей на массивы.В обоих случаях код обращается к массивам через указатели на первый элемент массива (например, host
- указатель на первый элемент с плавающей запятой, trans
- указатель на первый указатель на первый массив, который являетсяуказатель на первый элемент с плавающей точкой).alloc_matrix
структурирует массивы так, что вы можете легко обрабатывать данные как имеющие 1 или 2 измерения, потому что сами массивы являются смежными (они взяты из непрерывной области памяти, на которую указывает pool
).host[x][y]
обрабатывает данные как имеющие 2 измерения.(*host)[x*n+y]
(или host[0][x*n+y]
), где n
- размер одного массива данных, обрабатывает данные как имеющие 1 измерение.
То, что у вас есть:
float **GPU_output --> | float* | -> random memory location
| float* | -> random memory location
.... (size / sizeof(float**) pointers total)
| float* | -> random memory location
что хочешь
float **GPU_output --> | float* | --> | float |
| float |
...
| float |
| float* | --> | float |
| float |
...
| float |
...
| float* | --> | float |
| float |
...
| float |