我需要执行以下操作:
w[i] = scale * v[i] + point
scale 和 point 是固定的,而 v[]
是一个 4 位整数 vector 。
我需要为任意输入 vector v[]
计算 w[]
并且我想使用 AVX 内在函数来加速这个过程。但是,v[i]
是一个 4 位整数 vector 。
问题是如何使用内在函数对 4 位整数执行运算?我可以使用 8 位整数并以这种方式执行操作,但有没有办法执行以下操作:
[a,b] + [c,d] = [a+b,c+d]
[a,b] * [c,d] = [a * b,c * d]
(忽略溢出)
使用 AVX 内在函数,其中 [...,...] 是 8 位整数,a、b、c、d 是 4 位整数?
如果是,是否可以举一个简短的例子来说明它是如何工作的?
最佳答案
只是部分答案(仅添加)和伪代码(应该很容易扩展到 AVX2 内在函数):
uint8_t a, b; // input containing two nibbles each
uint8_t c = a + b; // add with (unwanted) carry between nibbles
uint8_t x = a ^ b ^ c; // bits which are result of a carry
x &= 0x10; // only bit 4 is of interest
c -= x; // undo carry of lower to upper nibble
如果已知 a
或 b
的第 4 位未设置(即高半字节的最低位),则可以将其排除在 的计算之外>x
.
至于乘法:如果所有产品的 scale
都相同,您可能可以通过一些移位和加/减(在必要时屏蔽溢出位)而逃脱。否则,恐怕你需要屏蔽掉每个 16 位字的 4 位,进行操作,最后将它们拼凑在一起。伪代码(没有AVX 8bit乘法,所以需要用16bit字来运算):
uint16_t m0=0xf, m1=0xf0, m2=0xf00, m3=0xf000; // masks for each nibble
uint16_t a, b; // input containing 4 nibbles each.
uint16_t p0 = (a*b) & m0; // lowest nibble, does not require masking a,b
uint16_t p1 = ((a>>4) * (b&m1)) & m1;
uint16_t p2 = ((a>>8) * (b&m2)) & m2;
uint16_t p3 = ((a>>12)* (b&m3)) & m3;
uint16_t result = p0 | p1 | p2 | p3; // join results together
关于c++ - AVX 4 位整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44011366/