在一般情况下,如何将索引表示法中的计算转换为SIMD操作序列?

时间:2016-11-30 23:04:14

标签: numpy math tensorflow linear-algebra simd

UPD :它的原始形式的问题制定得很差,因为我强烈混淆了术语(SIMD与矢量化计算)并给出了太广泛的例子,没有明确指出问题是什么; 我投票决定将其关闭与"不清楚你要问的是什么",我会在上面出现一个更好的问题链接

在数学中,人们通常会使用索引表示法描述n维张量计算,它看起来像:

A[i,j,k] = B[k,j] + C[d[k],i,B[k,j]] + d[k]*f[j] // for 0<i<N, 0<j<M, 0<k<K

但如果我们想使用任何SIMD库来有效地并行化该计算(并利用线性代数魔法),我们必须使用来自BLASnumpy,{的基元来表达它。 {1}},tensorflowOpenCL通常非常棘手。

[爱因斯坦符号] [1]中的表达式...通常通过[A_ijk*B_kj] [2]解决(使用np.einsumtensordot和{{1} }, 我猜?)。求和和其他元素操作也没关系,&#34; smart&#34;但是,索引非常棘手(特别是,如果索引在表达式中出现的次数多一次)。

我想知道是否有任何语言无关的库以某种形式(例如,上面的形式)采用表达式并将其转换为可以使用现有线性代数库高效执行的某些sum

有些库试图并行化循环计算(用户API通常在C ++中看起来像transpose或在python中看起来像Intermediate Representation),但我要问的是略有不同的东西:翻译abritary表达式在上面的形式中,有限的SIMD命令序列,如elementwise-ops,matvecs,tensordots等。

如果还没有与语言无关的解决方案,我个人对numpy计算感兴趣:)

1 个答案:

答案 0 :(得分:1)

关于代码的其他问题:

  • 我看到B[k,j]被用作索引和值。一切都是整数?如果没有,哪些部分是FP,转换发生在哪里?
  • 为什么i没有出现在右侧?相同的数据重复了N次吗?

哦,哎呀,所以你有一个聚集操作,索引来自d[k]B[k,j]。只有少数SIMD指令集支持此功能(例如AVX2)。

我主要使用Intel's x86 intrinsics手动矢量化C中的内容,(或自动矢量化并检查编译器的asm输出以确保它没有吮吸),所以IDK如果有&# 39;任何与平台无关的表达该操作的方式。

我不希望许多跨平台的SIMD语言提供聚集或任何建立在聚集之上的东西。我虽然没有使用numpy。 我不希望你找到包含聚集的BLAS,LAPACK或其他库函数,除非你去寻找这个确切问题的实现。

使用高效的聚集(例如Intel Skylake或Xeon Phi),如果您在j的循环中使用SIMD,它可以矢量化,因此您可以从B[]一次加载整个矢量,并且来自f[],并将其与持有d[k]广播的向量一起使用到每个位置。您可能希望存储转置结果矩阵,例如A[i][k][j],因此最终商店不必是散点图。你肯定需要避免在最里面的循环中循环k,因为这会使B[]的加载不连续,而你内部会有d[k]而不是f[j]内循环。

我对 GPGPU 做了很多事,但他们以不同的方式做了SIMD。它们不是像CPU那样使用短矢量,而是有效地将许多标量处理器组合在一起。 OpenCL或CUDA或其他任何热门的新GPGPU技术可以更有效地处理您的收集。

  

SIMD命令,如elementwise-ops,matvecs,tensordots等。

当我想到&#34; SIMD命令&#34;时,我会想到汇编指令(或ARM NEON,或其他),或至少编译为单个指令的C / C ++内在函数。 :P

矩阵向量产品不是单个&#34;指令&#34;。如果您使用该术语,则处理缓冲区的每个函数都将是&#34; SIMD指令&#34;。

你的问题的最后一部分似乎是要求编程语言独立版本的numpy,用于粘合高性能库函数。或者你是否认为可能会有一些东西可以对这些操作进行相互优化,所以你可以编写一些可以编译成矢量化循环的东西,这样就可以多次使用每个输入,而不必在单独的库调用中重新加载它? / p>

IDK是否有类似的东西,除了正常的C编译器自动矢量化循环数组外。