在某些情况下,GPU上的矩阵乘法/加法非常慢

时间:2015-07-24 14:55:39

标签: performance matlab gpu

我正在尝试让我的代码在我的GPU上运行,而不是CPU - 好吧,它正在运行,但不是很好。让我给出代码的相关部分:

u = zeros(n*L,1  ,'gpuArray'); ubar = zeros(n*L,1  ,'gpuArray');
y = zeros(n*L*d,1,'gpuArray'); ybar = zeros(n*L*d,1,'gpuArray');
v = zeros(n*L*d,1,'gpuArray');
w = zeros(n,1    ,'gpuArray');
z = zeros(n*L*d,1,'gpuArray');

...

    v_arg = v + sigma * (D * ubar - T_t * ybar);   (1)
    w_arg = w + sigma * Q * ubar;
    z_arg = z + sigma * ybar;

    v_new = back.dual.v(v_arg,w_arg,z_arg);
    w_new = back.dual.w(v_arg,w_arg,z_arg);
    z_new = back.dual.z(v_arg,w_arg,z_arg);

    u_arg = u - tau * (D_t * v_new + Q_t * w_new);   (2)
    y_arg = y - tau * (z_new - T * v_new);

    u_new = back.prim.u(u_arg,y_arg);
    y_new = back.prim.y(u_arg,y_arg);

    ubar_new = u_new + theta*(u_new - u);
    ybar_new = y_new + theta*(y_new - y);

...

% The dimensions of the matrices are as follows:
% D is (n*L*d,n*L); T is (n*L*d,n*L*d); Q is (n,n*L).

% Finally, "_t" denotes the transpose of a matrix. I found that it is a lot
% faster to define a new matrix that is the transpose, instead of doing the
% transpose operation each time.

两个标记的等式 - (1)和(2) - 是瓶颈。有关我的一次跑步所用的时间,请参见下图。 see the relevant MSDN documentation for details

最后,矩阵是稀疏矩阵 - 我正在使用Matlab 2015a,因此GPU上的稀疏矩阵很好(2014b不喜欢它们)。参数的特征尺寸如下:n = 60^2 = 3600, L = 48, d = 2

以下是CPU的相应时间。请注意,所调用的次数是接近的20倍,这就是为什么有些时间实际上更长。

GPU Times

有趣的是,我认为,在比较CPU和GPU时,不同线路的效率会有所不同。最后一行在GPU上略快,但倒数第二行在GPU上慢了大约6倍,第一行在GPU上慢了大约20倍。

如果需要更多信息,请告知我们。

以下是MVCE:

N = [50,50];
n = prod(N); d = numel(N);
L = 64;

sigma = 0.1;
tau   = 0.1;

D = spdiags([-ones(n*L*d,1), ones(n*L*d,1)],0:1,n*L*d,n*L);
D_t = D';

T = spdiags([-ones(L*d,1), ones(L*d,1)],0:1,L*d,L*d);
T = kron(T,speye(n));
T_t = T';

Q = sparse(n,n*L);
for j = 1:L
    Q(:,1+(j-1)*n:j*n) = speye(n); %#ok<SPRIX>
end
Q_t = Q';

u = zeros(n*L,1  ,'gpuArray');
y = zeros(n*L*d,1,'gpuArray');
v = zeros(n*L*d,1,'gpuArray');
w = zeros(n,1    ,'gpuArray');
z = zeros(n*L*d,1,'gpuArray');

count = 0;
count_max = 1000;   % Choose count_max as the maximum number of iterations
while count <= count_max
    v = v + sigma * (D * u - T_t * y);
    w = w + sigma * Q * u;
    z = z + sigma * y;

    u = u - tau * (D_t * v + Q_t * w);
    y = y - tau * (z - T * v);

    count = count + 1;

    if mod(count,10) == 0
        fprintf('count = %1g\n',count)
    end
end

1 个答案:

答案 0 :(得分:1)

解决!问题在于,当我将矩阵分配给GPU时,我正在定义一个新的矩阵D_t作为转置 - 这是因为我没有必要在GPU上进行矩阵的转置每次都节省了大量的时间 - 我没有将转置矩阵分配给GPU!

正如rayryeng指出的那样,道德是确保你的所有数组都是gpuArray希望我的错误会阻止其他人犯同样的错误! :)