我最初提交此任务是一个基本的并行化问题,由@Divakar回答。他的工作将成为这一后续行动的基础。他建议通过移植代码来在GPU上进行计算,可以进一步提高速度。我一直在研究这个大道,并且能够将迭代循环中的矢量化解决方案从我的案例中提高15%,加速到50%。然而,进一步的修补并未导致许多其他改进。我首先担心的是硬件不是特别强大,但在我们的团队能够在新硬件上花钱之前,我们希望从我们当前设置的代码中看到更高的效率:
XGPU = gpuArray(X);
YGPU = gpuArray(Y);
HGPU = gpuArray(H);
EGPU = gpuArray(E);
% Perform kron format elementwise multiplication betwen the first two dims
% of X and Y, keeping the third dim aligned and "pushing out" leftover dims
% from Y to the back
mults = bsxfun(@mtimes,permute(XGPU,[4,2,5,1,3]),permute(YGPU,[1,6,2,7,3,4,5]));
mults3D = reshape(mults,N2,N2,[]);
clear mults;
Emults3D = reshape(EGPU*reshape(mults3D,size(mults3D,1),[]),size(mults3D));
% Trace summations by using linear indices of diagonal on 3D slices in Emults3D
MN = N2;
idx = 1:MN+1:MN^2;
idx2D = bsxfun(@plus,idx(:),MN^2*(0:size(Emults3D,3)-1));
pr_sums = sum(Emults3D(idx2D),1);
clear Emults3D;
clear idx2D;
% Perform "M/pr" equivalent elementwise divisions and then use
% matrix-multiplication to reduce the iterative summations
Mp = bsxfun(@rdivide,mults3D,reshape(pr_sums,1,1,[]));
clear pr_sums;
clear mults3D;
outGPU = reshape(Mp,[],size(Mp,3))*reshape(permute(HGPU,[3,1,2]),[],1);
outGPU = reshape(outGPU,N2,N2)/(sum(sum(sum(HGPU))));
clear Mp;
out = gather(outGPU);
一些相关信息:X是3D MxMxN阵列。 Y是5D MxNxNxPxP阵列。 H是尺寸为MxPxP的2D直方图切片的3D结构。 E是M ^ 2xM ^ 2矩阵布尔掩码。
目前存在瓶颈的计算是Emults3D的创建和Mp的创建。
我的问题如下:
有更好的方法可以更好地处理GPU内存分配吗?即使是使用4GB VRAM的远程硬件测试,也无法完整地完成计算,需要进行截断和修剪。
编写CUDA内核是否会改善并行化和加速以及我应该针对哪些计算?
这些线的哪些部分实际上很慢:重塑或乘法/除法?在任何一种情况下,是否有其他并行化的替代方案,如pagefun或类似的,以减少计算时间?
我将注意到,一旦计算算法得到改进,我计划利用gpuArray构造函数在开始时删除尽可能多的host-> gpu传输。这还包括在代码的后期等待构建E和H,这样他们就不会在开始时浪费宝贵的VRAM空间。