【问题标题】:Matlab: Arrayfun with MatricesMatlab:带有矩阵的 Arrayfun
【发布时间】:2014-10-14 12:45:08
【问题描述】:

我正在尝试使用arrayfun重写以下代码

A = ones(3,3,3)
for i = 1:3
    B(i) = trace(A(:,:,i));
end

我希望尝试过

f = @(x) trace(x)
B = arrayfun(f, A);

但这只是(如您所料)跟踪每个人A(i,j,k) 而不是我想要的A(:,:,i)。然后我尝试将A{i}=ones(3,3) 声明为一个单元格并传递给arrayfun,但这也不起作用。

如何在 Matlab 中对矩阵上的函数进行向量化?

【问题讨论】:

  • 想知道这里提供的任何一种解决方案是否适合您?
  • 您好 Divikar,这些解决方案确实有效,但都没有给我一个通用的方法来对 GPU 上的矩阵函数进行矢量化,我可以测试......但是。不幸的是,我可以访问的服务器正在运行没有 pagefun 的 Matlab 版本,但正在周四升级。

标签: arrays matlab matrix vectorization


【解决方案1】:

基于bsxfun 的矢量化解决方案,ab(使用)如何定义trace - sum of diagonal elements -

%// Get size of A
[m,n,r] = size(A) 

%// Get indices of the diagonal elements for each 3D "slice" as columns of idx
idx = bsxfun(@plus,[1:m+1:m*n]',[0:r-1]*m*n) %//'

%// Thus, for your 3 x 3 x 3 case, idx would be -
%//idx =
%//      1    10    19
%//      5    14    23
%//      9    18    27
%// and these are the linear indices to the diagonal elements to each `3D` slide.

%//Index into A with idx and sum along columns to get each element of desired output
B = sum(A(idx),1)

如果您希望避免使用不必要的额外变量而造成工作区混乱,请避免使用 idx 和 -

B = sum(A(bsxfun(@plus,[1:m+1:m*n]',[0:r-1]*m*n)),1)

用于使用 GPU

如果你必须使用GPUs,你可以用gpuArray(A)将它们声明为gpuArrays,然后涉及A的后续工作将在GPU上完成,你会得到一个gpuArray的输出,你可以得到使用gather(..) 作为 CPU 变量返回。

因此,完整的代码如下所示 -

[m,n,r] = size(A); %// Get size
gpu_A = gpuArray(A); %// copy data from CPU to GPU

%// Perform calculations on GPU
gpu_B = sum(gpu_A(bsxfun(@plus,[1:m+1:m*n]',[0:r-1]*m*n)),1); %//'

B = gather(gpu_B); %// get back output onto CPU

快速测试:使用 GTX 750 Ti(我可以使用),这似乎让我的循环代码速度提高了 3 倍。

【讨论】:

    【解决方案2】:

    如果你真的想使用arrayfun,你可以试试这样的技巧:

    arrayfun(@(i)trace(A(:,:,i)), 1:size(A,3))
    

    但请注意,arrayfun 不是矢量化!!,它只是循环的包装器,并且由于增加了开销,通常比循环慢。

    虽然同样不是矢量化,但要以第二种方式进行,您应该更改为 cellfun。即如果A{i} = ones(3,3) 那么

    cellfun(@(x)trace(x), A)
    

    【讨论】:

    • 当我在 GPU 上运行代码时,我想使用 arrayfun。我认为arrayfun 包装器在这种情况下会加快我的计算速度是否正确?
    • @rwolst Think pagefun 相当于 GPU 的 araryfun。不过,请通过查看官方文档来确保这一点。
    • @Divakar:不,arrayfun 是将循环推送到 GPU 上的好方法。当然,关于并行化开销的常见警告也适用。
    • @Divakar:抱歉,“好”可能不是最合适的词。我的意思是“一种让事情真正在 GPU 上运行的方式”。 Pagefun 很可能更优化,因此仅限于某些功能。
    • @Dan:需要将数组定义为gpuArrays,需要并行计算工具箱。
    猜你喜欢
    • 2012-03-16
    • 1970-01-01
    • 1970-01-01
    • 2018-08-26
    • 1970-01-01
    • 1970-01-01
    • 2020-02-23
    • 2019-10-17
    • 2017-07-15
    相关资源
    最近更新 更多