Я написал фрагмент кода в MatLab (2018a), который является гибридом между стандартным кодом Matlab и кодом CUDA, который я связал с помощью компиляции с mexcuda.Основной цикл в моем коде содержит интерполяцию матрицы, скажем, от размера [nxm] до [N x M].Я ускорил эту часть с помощью графического процессора.Поскольку эта интерполяция находится в цикле, и поскольку размеры матриц, которые я интерполирую (как до, так и после), одинаковы на каждой итерации цикла, я хочу ускорить приложение, предварительно выделив массив выходного размера наGPU.Поэтому я хочу сделать что-то вроде: zeros(N,M,'gpuArray')
один раз в начале, предоставить его в качестве входных данных для функции mexFunction и записать интерполированную матрицу в этот массив.Это сэкономит немало времени на выделение ([N_iterations-1] * alloc_time, грубо говоря).
Моя проблема сейчас такова: я не могу понять, возможно ли это.Используя mexFunction () в качестве точки входа, единственный известный мне способ получения входных массивов - это использовать что-то вроде:
mxGPUArray const *in = mxGPUCreateFromMxArray(prhs[0]);
float const *dev_in = (float const *)(mxGPUGetDataReadOnly(in));
, но, как следует из названия, это дает разрешение только на чтение,Я не могу использовать mxGPUGetData(in)
, потому что mxGPUArray равен const
, с ним нельзя инициализировать неконстантную сущность.Кто-нибудь знает, есть ли способ обойти эту проблему, которая не включает выделение массива внутри mexFunction?
EDIT:
Код ниже показывает два примера кода C, где первыйаналогия с моим текущим кодом, а вторая - это то, к чему я стремлюсь:
Текущий:
#include "stdio.h"
int main(const int argc, const char *argv[]) {
// Allocate input matrix and fill from input arguments
FILE *fPtr; fPtr = fopen(argv[1],"rb");
double *mat_in = malloc(n*m*sizeof(*mat_in));
mat_in = fread(mat_in, sizeof(*mat_in), n*m, fPtr);
fclose(fPtr);
double *mat_out;
for (int it = 0, it < 1000, it++) {
// Allocate output array and fill it;
mat_out = malloc(N*M*sizeof(*mat_out));
interpolation_function(mat_in, mat_out);
// Do stuff with mat_out
free(mat_out);
}
// Free mat_in, do more stuff and/or exit program
Идея:
#include "stdio.h"
int main(const int argc, const char *argv[]) {
// Allocate input matrix and fill from input arguments
FILE *fPtr; fPtr = fopen(argv[1],"rb");
double *mat_in = malloc(n*m*sizeof(*mat_in));
mat_in = fread(mat_in, sizeof(*mat_in), n*m, fPtr);
fclose(fPtr);
// Allocate output array once at the start:
double *mat_out = malloc(N*M*sizeof(*mat_out));
for (int it = 0, it < 1000, it++) {
interpolation_function(mat_in, mat_out); // Fills mat_out
// Do stuff with mat_out here;
}
free(mat_out);
// Free mat_in, do more stuff and/or exit program
Выше приведены два ((по крайней мере, на мой взгляд) аналогия для следующего гибридного кода Matlab-Cuda:
Ток (Matlab);функция mexcuda должна выделить память для интерполяции ввода (:,:, indx)
accumresult = zeros(N,M);
input = randn(100,100,1000);
for indx = 1:1000
input_slice = mexcuda_interpolation( input(:,:,indx) );
accumresult = accumresult + foo( input_slice, other_parameters);
end
Идея: выделение памяти перемещено из функции mexcuda (и, следовательно, из цикла ядра)и функции mexcuda нужно только получить указатель на этот (доступный для записи) массив;
accumresult = zeros(N,M,'gpuArray');
placeholder = zeros(N,M,'gpuArray'); % Memory allocated on GPU once here
input = randn(100,100,1000);
for indx = 1:1000
accumresult = accumresult + foo( mexcuda_interpolation(input(:,:,indx)), placeholder, other_parameters);
%mexcuda_interpolation() somehow gets a pointer to the allocated memory which it can write to
end
Обратите внимание, что действительно есть возможность распараллелить это дальше: как уже говорилось, я на промежуточном этапе распараллеливаниявсе дело.