我在 MatLab (2018a) 中编写了一段代码,它是标准 matlab 代码和 CUDA 代码的混合体,我使用编译与 mexcuda 将其链接起来。我的代码中的核心循环包含一个矩阵的插值,比如从大小 [nxm] 到 [N x M]。我已经使用 GPU 加快了这部分的速度。由于此插值在循环内,并且由于我插值的矩阵的大小(之前和之后)在循环的每次迭代中都是相同的,我想通过预先分配输出大小的数组来加速应用程序显卡。所以我想做类似的事情:zeros(N,M,'gpuArray')
在开始时,将它作为输入提供给 mexFunction,然后将插值矩阵写入这个数组。这将节省相当多的分配时间([N_iterations-1]*allocation_time,粗略地说)。
我现在的问题是:我不知道这是否可能。使用 mexFunction() 作为入口点,我知道检索输入数组的唯一方法是使用以下内容:
mxGPUArray const *in = mxGPUCreateFromMxArray(prhs[0]);
float const *dev_in = (float const *)(mxGPUGetDataReadOnly(in));
但是,顾名思义,这会导致只读权限。我不能使用mxGPUGetData(in)
,因为 mxGPUArray 是const
,不能用它初始化非常量实体。有谁知道是否有解决这个问题的方法不涉及在 mexFunction 内分配数组?
编辑:
下面的代码显示了两个 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 函数需要为 input(:,:,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
请注意,确实有可能进一步并行化:如前所述,我正处于并行化整个事物的中间步骤。