【问题标题】:for every row, reshape and calculate eigenvectors in a vectorized way对于每一行,以矢量化的方式重塑和计算特征向量
【发布时间】:2014-12-13 17:07:30
【问题描述】:

我想解决这个问题很久了,但还没有成功。我假设我会使用 arrayfun,但我还想不通。感谢帮助。问题来了:

给定一个多行 N^2 列的矩阵,将每一行重塑为 NxN 矩阵并计算特征值,并以向量化方式执行此操作,而不使用 for 循环。例如

A= 
0.6060168   0.8340029   0.0064574   0.7133187
0.6325375   0.0919912   0.5692567   0.7432627
0.8292699   0.5136958   0.4171895   0.2530783
0.7966113   0.1975865   0.6687064   0.3226548
0.0163615   0.2123476   0.9868179   0.1478827

for every **i**

m=reshape(A(i,:),2,2)

[vc vl]=eig(m)

我倾向于做类似的事情

f = @(x) eig(reshape(x,2,2))

arrayfun(f,A)

但我当然会遇到类似

的错误
octave:5> arrayfun(f,A)
error: reshape: can't reshape 1x1 array to 2x2 array
error: evaluating argument list element number 1
error: evaluating argument list element number 1
error: called from:
error:    at line -1, column -1
error: cellfun: too many output arguments
error:   /usr/share/octave/3.2.4/m/general/arrayfun.m at line 168, column 21

【问题讨论】:

    标签: octave


    【解决方案1】:
    A = [0.6060168 0.8340029 0.0064574 0.7133187;
    0.6325375 0.0919912 0.5692567 0.7432627;
    0.8292699 0.5136958 0.4171895 0.2530783;
    0.7966113 0.1975865 0.6687064 0.3226548;
    0.0163615 0.2123476 0.9868179 0.1478827];
    
    N = 2;
    [mc, ml] = arrayfun (@(row) eig (reshape (A (row, :), N, N)), 1:rows(A), "UniformOutput", false)
    
    mc = 
    {
      [1,1] =
    
        -0.170783  -0.044626
         0.985309  -0.999004
    
      [1,2] =
    
        -0.95343  -0.89053
         0.30161  -0.45492
    
      (cropped)
    
    }
    ml = 
    {
      [1,1] =
    
    Diagonal Matrix
    
         0.56876         0
               0   0.75057
    
      [1,2] =
    
    Diagonal Matrix
    
         0.45246         0
               0   0.92334
    (cropped)
    

    【讨论】:

    • 非常感谢。这是一个了不起的答案。你让我开心!
    • 为什么很棒?我认为还有其他可能性。这是作业吗?
    • 不,这不是功课(我的功课远远超出了我多年的功课!)。它与固态物理学中的常见计算有关。如果您或其他人有时间在此指出,我将非常乐意看到其他可能性。在这个过程中,我意识到我的 Octave 知识仍然是初级的(虽然我的编程经验不是 (F90,linux,bash) )。我很好奇矢量化会在多大程度上加快我的计算速度。完成基准测试后,我会在此处指出。
    • 现在我的代码比以前快了 4 倍。现在看来,计算与 nrow 线性缩放,而不是 nrow^2。感谢您的帮助。
    【解决方案2】:

    使用Ndpar package,可以在多个内核上并行计算。 借用安迪的回答,

    pkg load ndpar
    
    A = [0.6060168 0.8340029 0.0064574 0.7133187;
    0.6325375 0.0919912 0.5692567 0.7432627;
    0.8292699 0.5136958 0.4171895 0.2530783;
    0.7966113 0.1975865 0.6687064 0.3226548;
    0.0163615 0.2123476 0.9868179 0.1478827];
    
    N = 2;
    [eigenvectors, eigenvalues] = ndpar_arrayfun(nproc, 
                                    @(row) eig(reshape(row, N, N)), 
                                    A, "IdxDimensions", 1, "Uniformoutput", false)
    

    产生相同的输出。


    编辑 - 或者使用来自 octave-forge parallel 包的原始 pararrayfun

    [eigenvectors, eigenvalues] = pararrayfun(nproc, 
                                    @(row_idx) eig(reshape(A(row_idx, :), N, N)), 
                                    1:rows(A), "UniformOutput", false)
    

    【讨论】:

    • 以前没听说过这个包。肯定会有用的。谢谢。
    • @huntj 您是否与 Olaf 谈过将这些更改包含在 octave-forge 并行中?我认为你应该给 Octave 维护者列表写一封电子邮件并要求审查。
    • @Andy 实际上,大约一年前,我提交了一个初步补丁,但被 Olaf 拒绝。也许以后。
    • 我尝试在双核机器上同时使用 ndpar_arrayfun 和 pararrayfun 运行我的代码。然而,事实证明,代码花费的时间是以前的 4 倍。可能这些对 ncore >= 2 有用。不过感谢您的建议。我相信它们在其他情况下也会很有用。
    • @TuxOnPogoStick 加速比高度依赖于要并行化的函数的执行时间,相对于开销时间。如果矩阵真的是 2x2,那么这个函数确实太快了。
    猜你喜欢
    • 2016-05-28
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多