高效的张量乘法

Efficient Tensor Multiplication

我有一个表示高维张量的矩阵,原则上可以是 N 维,但每个维度的大小都相同。假设我想计算以下内容:

eqn1

并且C通过

存储为矩阵

eqn2

其中有一些从 ij 到 I 和 kl 到 J 的映射。

我可以使用嵌套的 for 循环来做到这一点,其中我的张量的每个维度的大小都是 3 via

for (int i=0; i<3; i++){
    for (int j=0; j<3; j++){
        I = map_ij_to_I(i,j);
        for (int k=0; k<3; k++){
            for (int l=0; l<3; l++){
                J = map_kl_to_J(k,l);
                D(I,J) = 0.;
                for (int m=0; m<3; m++){
                    for (int n=0; n<3; n++){
                        M = map_mn_to_M(m,n);
                        D(I,J) += a(i,m)*C(M,J)*b(j,n);
                    }
                }
            }
        }
    }
}

但这很混乱而且效率不高。我正在使用 Eigen 矩阵库,所以我怀疑可能有比 for 循环或单独编码每个条目更好的方法。我尝试了不受支持的张量库,发现它比我的显式循环慢。有什么想法吗?

作为奖励问题,我将如何有效地计算如下内容?

eqn3

编译器的优化器会在后台为您做很多工作。一次,展开具有恒定迭代次数的循环。这可能是您的代码比库更快的原因。

我建议看一下经过优化后生成的程序集,以真正掌握可以优化的位置以及编译后程序的真实情况。

当然,您可以考虑在 CPU(多线程)或 GPU(cuda、OpenCL、OpenAcc 等)上的并行实现。

至于奖金问题,如果您考虑将其写成两个嵌套循环,我建议重新排列表达式,使 a_km 项位于两个和之间。不需要在内部和中执行乘法,因为它不依赖于 n。尽管这在现代 CPUs...

中可能只会带来轻微的性能优势