据我所知,具有串行数据依赖项(例如A[i]=A[i-1]
)的循环无法矢量化。
但我不确定A[I]=A[I 1]是否是原始数据依赖关系,这个循环是否可以矢量化?
for(i = 0; i < n - 1; i++) {
A[i] += A[i + 1];
}
下面的循环可以矢量化。
for(i = 0; i < n - 1; i++) {
A[i] += A[i + 1];
}
我们可以用另一种方式编写操作:
Vector A = ...; // 1, 2, 3, 4, 5
Vector B = ShiftLeft(A); // 2, 3, 4, 5, 0 you dont create new array, no performance loss
Vector C = A + B; // 3, 5, 7, 9, 5
将其矢量化并不困难。。作为Peter Cordes,什么??嗨,彼得^ ^。正如彼得所说,A[i]=A[i-1] 更难,可能是另一种情况。
您的循环计数器正在增加(i),因此您正在向前看,而不是向后看。这意味着您只需读取两次相同的原始输入元素,而不是重新读取任何最近的输出。因此,没有串行依赖关系。
只需使用编译器进行尝试,就可以看到向量加载/存储,而不是标量。(在为x86编译时,很容易用整数而不是FP来区分差异)。e、 g.开启https://godbolt.org/带gcc或clang<代码>-O3<代码>
在具有高效未对齐加载的机器上(如现代x86),编译器可能只会加载
a[i 0..3]
和a[i 0..3]
,但另一个选项是无序移动以创建偏移向量,例如使用x86 SSSE3palignr
,这是为此而设计的,在Core 2上非常有用(它没有高效的SIMD未对齐加载)。
GCC和clang都使用SSE2对x86-64进行矢量化(SSE2是x86-64的基线)https://godbolt.org/z/HdNsvC-GCC9。1对于x86-64(默认值为-mtune=generic,只有SSE2可用)选择执行2倍的加载添加存储。叮当声8。0选择展开(像往常一样)并从A[i 1 4*展开0..3]
加载,然后使用shufps创建向量。中间端优化器可能使用了一个配方,该配方在palignr方面很好,但一旦达到代码gen,就必须对其进行仿真,并且只有SSE2,而不是SSSE3。此外,输入指针很可能是16字节对齐的,因此从与之相关的16*n 4字节加载向量是不幸的。但无论如何,它都会在最近的Intel CPU上造成洗牌吞吐量瓶颈。
使用AVX1而不是AVX2(例如,march=sandybridge)会造成一个搞笑的混乱:使用256位FP洗牌分多个步骤模拟256位的换行符,然后将整数SIMD解包为128位向量(压缩32位add),然后将vinsertf128解包为256位存储。SnB甚至没有256位的加载/存储单元,因此这些UOP需要2个周期才能运行,并且对未对齐数据的惩罚比通常的要大得多。
A[i]=A[i-1]
更难矢量化,但使用高效的洗牌可以加速,尤其是使用浮点,其中串行依赖的延迟会造成更大的伤害。
>
Intel cpu上的SIMD前缀和
带SSE的并行前缀(累计)和
或者通常,如果前面有一个跨步的封闭式公式,您可以在SIMD向量的元素中并行运行该公式,如中,是否可以在计算中对串行依赖项使用SIMD,如指数移动平均滤波器?
问题内容: 想要改善这篇文章吗? 提供此问题的详细答案,包括引文和答案正确的解释。答案不够详细的答案可能会被编辑或删除。 主持人注意: 请不要编辑代码或删除此声明。空格模式可能是问题的一部分,因此不应不必要地对其进行篡改。如果您处于“空白无关紧要”的阵营中,则应该能够原样接受代码。 有可能用JavaScript 评估吗? 这是一家大型科技公司提出的面试问题。它发生在两周前,但我仍在努力寻找答案。我
带有元素v1,v2,v3,...,vn的向量v的大小由公式给出 - | V | =√(v1 2 + v2 2 + v3 2 + ... + vn 2 ) 您需要采取以下步骤来计算向量的大小 - 使用array multiplication (。*)获取向量的array multiplication 。 这产生了矢量sv,其元素是矢量v的元素的平方。 sv = v。* v; 使用sum函数得到向量v
转置操作将列向量更改为行向量,反之亦然。 转置操作由单引号(')表示。 例子 (Example) 使用以下代码创建脚本文件 - r = [ 1 2 3 4 ]; tr = r'; v = [1;2;3;4]; tv = v'; disp(tr); disp(tv); 运行该文件时,它显示以下结果 - 1 2 3 4 1 2 3 4
在Spring DI中,将autowired字段声明为可选字段可以使客户端不向其注入任何值。使用Java EE的CDI是否可能做到这一点?我试过可选但失败了。我想知道是否有一个等价的机制我可以使用。 下面是我尝试的: 我得到一个错误消息:线程“main”org.jboss.weld.exceptions.deploymentexception:WELD-001408在注入点[[BackedAnno
这句看似微不足道的台词摘自我的迈克·巴纳汉的C书 我可以理解隐式提升是如何根据操作数的类型在诸如之类的表达式中发挥作用的,但我无法理解在诸如之类的表达式中,隐式提升是如何以及在何种情况下发挥作用的,其中b是任何合法的操作数。你能解释一下,然后给出一个恰当的例子吗? 摘录如下: 通常的算术转换应用于运算符的二进制形式的两个操作数。仅对运算符的一元形式的操作数执行积分提升。 更新: 为了避免被忽视,我
问题内容: java.lang.Math#min(double,double): 在那种情况下可以退货?NaN 似乎是在什么时候,但我无法想象一个例子。你能提供一个吗? 问题答案: 一个简单的例子是 BTW Double.compare()确实将NaN视为相等 对于多个线程,这对于任何类型和值都是可行的。例如