Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 是否可以使用arrayfun()加速此gpuArray计算(或其他方式)?_Performance_Matlab_Gpu_Gpuarray - Fatal编程技术网

Performance 是否可以使用arrayfun()加速此gpuArray计算(或其他方式)?

Performance 是否可以使用arrayfun()加速此gpuArray计算(或其他方式)?,performance,matlab,gpu,gpuarray,Performance,Matlab,Gpu,Gpuarray,我有一个复杂的矩阵a,我想根据a=exp(-1i*(a+abs(a)。^2))修改它Nt次。A的大小通常为1000x1000,运行次数约为10000次 我希望减少执行这些操作所需的时间。对于CPU上的1000次迭代,我测量大约6.4秒。之后,我能够将其移动到GPU,从而将所需时间减少到0.07秒(令人难以置信的x91改进!)。到目前为止还不错 然而,我现在也阅读了文档,其中描述了如果我们同时使用arrayfun(),有时我们如何在元素计算方面找到进一步的改进。如果我试着遵循教程,所花费的时间实际

我有一个复杂的矩阵
a
,我想根据
a=exp(-1i*(a+abs(a)。^2))
修改它
Nt
次。
A
的大小通常为1000x1000,运行次数约为10000次

我希望减少执行这些操作所需的时间。对于CPU上的1000次迭代,我测量大约6.4秒。之后,我能够将其移动到GPU,从而将所需时间减少到0.07秒(令人难以置信的x91改进!)。到目前为止还不错

然而,我现在也阅读了文档,其中描述了如果我们同时使用
arrayfun()
,有时我们如何在元素计算方面找到进一步的改进。如果我试着遵循教程,所花费的时间实际上更糟糕,计时为0.47秒。我的测试如下所示:

Nt = 1000; % Number of times to run each method
test_functionFcn = @test_function;

A = rand( 500, 600, 'double' ) + rand( 500, 600, 'double' )*1i; % Define an initial complex matrix
    
gpu_A = gpuArray(A); % Transfer matrix to a GPU array

%%%%%%%%%%%%%%%%%%%% Run the calculation Nt times on CPU only %%%%%%%%%%%%%%%%%%%%
cpu_data_out = A;
tic
for k = 1:Nt 
    cpu_data_out = test_function( cpu_data_out );
end
tcpu = toc;

%%%%%%%%%%%%%%%%% Run the calculation Nt times on GPU directly %%%%%%%%%%%%%%%%%%%%
gpu_data_out = gpu_A;
tic
for k = 1:Nt
    gpu_data_out = test_function(gpu_data_out);
end
tgpu = toc;

%%%%%%%%%%%%%% Run the calculation Nt times on GPU using arrayfun() %%%%%%%%%%%%%%
gpuarrayfun_data_out = gpu_A;
tic
for k = 1:Nt
    gpuarrayfun_data_out = arrayfun( test_functionFcn, gpuarrayfun_data_out );
end
tgpu_arrayfun = toc;

%%% Print results %%%
fprintf( 'Time taken using only CPU: %g\n', tcpu );
fprintf( 'Time taken using gpuArray directly: %g\n', tgpu );
fprintf( 'Time taken using GPU + arrayfun(): %g\n', tgpu_arrayfun );

%%% Function to operate on matrices %%%
function y = test_function(x)
y = exp(-1i*(x + abs(x).^2));
end
结果是:

Time taken using only CPU: 6.38785
Time taken using gpuArray directly: 0.0680587
Time taken using GPU + arrayfun(): 0.474612
我的问题是:

  • 在这种情况下,我是否正确地使用了arrayfun(),预计arrayfun()会更糟
  • 如果是这样的话,而且人们真的期望它比直接gpuArray方法慢,那么有没有任何简单(即非MEX)的方法来加速这种计算?(我看到他们也提到使用例如)
  • 提前谢谢你的建议

    (图形卡是Nvidia Quadro M4000,我正在运行Matlab R2017a)

    编辑 在阅读了@Edric的答案之后,我认为展示更多更广泛的代码是很重要的。在OP中我没有提到的一点是,在我实际的主代码中,在k=1:Nt循环中有一个额外的操作,它是一个稀疏的三对角矩阵转置的矩阵乘法。下面是一个更加充实的MWE,它描述了真正发生的事情:

    Nt = 1000; % Number of times to run each method
    N_rows = 500;
    N_cols = 600;
    test_functionFcn = @test_function;
    A = rand( N_rows, N_cols, 'double' ) + rand( N_rows, N_cols, 'double' )*1i; % Define an initial complex matrix
    %%% Generate a sparse, tridiagonal, square transformation matrix %%%%%%%%
    mm = 10*ones(N_cols,1); % Subdiagonal elements
    dd = 20*ones(N_cols,1); % Main diagonal elements
    pp = 30*ones(N_cols,1); % Superdiagonal elements
    M = spdiags([mm dd pp],-1:1,N_cols,N_cols);
    M(1,1) = 6; % Set a couple of other entries
    M(2,1) = 3;
    %%%%%%%%%%%%%%%%%%%% Run the calculation Nt times on CPU only %%%%%%%%%%%%
    cpu_data_out = A;
    for k = 1:Nt 
        cpu_data_out = test_function( cpu_data_out );
        cpu_data_out = cpu_data_out*M.';
    end
    %%% Function to operate on matrices %%%
    function y = test_function(x)
    y = exp(-1i*(x + abs(x).^2));
    end
    

    我很抱歉没有将其包括在OP中-我当时没有意识到它可能与解决方案相关。这会改变情况吗?使用GPU上的arrayfun()是否仍有收益,或者现在不适合转换为arrayfun()?

    这里有几点。首先,(也是最重要的)到,您需要使用或在调用
    toc
    之前插入对的调用。这是因为工作是在GPU上异步启动的,只有等待工作完成才能获得准确的时间。通过这些细微的修改,在我的GPU上,
    gpuArray
    方法的时间为0.09秒,
    arrayfun
    版本的时间为0.18秒

    运行一个GPU操作循环通常效率低下,因此您可以在这里获得的主要好处是将循环推到
    arrayfun
    函数体中,使该循环直接在GPU上运行。像这样:

    %%% Function to operate on matrices %%%
    function x = test_function(x,Nt)
    for ii = 1:Nt
        x = exp(-1i*(x + abs(x).^2));
    end
    end
    

    您需要像调用
    A=arrayfun(@test\u function,A,Nt)
    一样调用它。在我的GPU上,这将
    arrayfun
    时间缩短到0.05秒,大约是普通
    gpuArray
    版本的两倍。

    Hi@Edric,非常感谢您的回答。1) 感谢您对gputimeit的建议-我不知道获得适当的基准测试有多么重要。我以后会用这个。2) 我想我现在从您的示例中更好地了解了arrayfun()如何带来收益。不过,我认为这在我的实际代码中不起作用——我已经更新了这个问题,以便您可以看到更多内容。很抱歉之前没有包括这个。考虑到这些额外的细节,你对如何加速有什么看法?谢谢你的支持。