我有一个float8矢量类型,我使用矢量分量寻址将矢量的分量乘以如下(注意下面的变量v实际上不是常数);
float8 v = (float8) (1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f);
float result = v.s0 * v.s1 * v.s2 * v.s3 * v.s4 * v.s5 * v.s6 * v.s7;
但是,这可以防止在使用“英特尔代码”构建器进行编译时对内核进行矢量化。
Device build started
Device build done
Kernel <test> was not vectorized
为了解决这个问题,我开始创建向量的副本,屏蔽所需的组件并将它们全部放在一起,然后再尝试调用点函数,但这一切看起来效率都很低且很复杂。
因此,我的问题是如何在高效的矢量化庄园中将我的矢量分量相乘?
答案 0 :(得分:1)
我的评论错误,因为它不是结果中您需要的点积。它只是8个数字的乘法。并行工作数据应该是并行的,而不是在同一个容器中。如果你想将s0 s1 s2 ... s7相乘,那么你将它们放在连续的矢量变量
中variable-1: s0 p0 r0 q0 .... z0
variable-2: s1 p1 r1 q1 .... z1
variable-8: s7 p7 .... z7
你可以用SIMD速度乘以那些,并使用float8类型一次进行8次乘法,并根据需要连续多次,而不仅仅是8次。
在每次乘法时,您都有责任检查错误和溢出。但是当硬件在一条指令中进行8次乘法时,你想要哪种顺序?您希望它们以递增的索引顺序(串行,慢速)或类似于树元素的成对乘法的方式相乘(乘法越少,速度越快,但会得到不同的结果)?有时候操作顺序可能很重要。
如果是gpu ,只需乘以项目和指令级并行+ gpu的超线程引擎即可实现效率。 如果是cpu ,首先应检查你的cpu是否支持垂直乘法指令(我怀疑这种情况存在),如果不存在则需要乘以数组元素不是矢量元素。这应该更容易矢量化,因为它是主存储器上的连续数据,因为cpu没有对本地存储器进行显式控制。