我将使用什么内在函数来对x86_64上的以下内容进行矢量化(如果它甚至可以进行矢量化)?
double myNum = 0;
for(int i=0;i<n;i++){
myNum += a[b[i]] * c[i]; //b[i] = int, a[b[i]] = double, c[i] = double
}
Run Code Online (Sandbox Code Playgroud) 我想使用SSE将无符号短数组转换为float.让我们说吧
__m128i xVal; // Has 8 16-bit unsigned integers
__m128 y1, y2; // 2 xmm registers for 8 float values
Run Code Online (Sandbox Code Playgroud)
我希望y1中的前4个uint16和y2中的下一个4 uint16.需要知道哪些内在使用.
我编写了该函数int compare_16bytes(__m128i lhs, __m128i rhs),以便使用SSE指令比较两个16字节数:该函数返回执行比较后相等的字节数.
现在我想使用上面的函数来比较任意长度的两个字节数组:长度可能不是16字节的倍数,所以我需要处理这个问题.我怎样才能完成下面这个功能的实现?我怎样才能改进下面的功能?
int fast_compare(const char* s, const char* t, int length)
{
int result = 0;
const char* sPtr = s;
const char* tPtr = t;
while(...)
{
const __m128i* lhs = (const __m128i*)sPtr;
const __m128i* rhs = (const __m128i*)tPtr;
// compare the next 16 bytes of s and t
result += compare_16bytes(*lhs,*rhs);
sPtr += 16;
tPtr += 16;
}
return result;
}
Run Code Online (Sandbox Code Playgroud) 哪些指令用于比较由4*32位浮点值组成的两个128位向量?
是否存在将双方的NaN值视为相等的指令?如果不是,提供反身性的解决方案(即NaN等于NaN)的性能影响有多大?
我听说,与IEEE语义相比,确保反身性会产生显着的性能影响,因为NaN不等于自己,我想知道这种影响是否会很大.
我知道您在处理浮点值时通常需要使用epsilon比较而不是精确的质量.但是这个问题是关于完全相等的比较,例如,您可以使用它来消除哈希集中的重复值.
要求
+0并且-0必须相等.NaN 必须与自己相等.true如果两个向量中的所有四个float元素相同,则结果应为布尔值,如果至少一个元素不同,则结果为false.其中true由标量整数1和falseby表示0.测试用例
(NaN, 0, 0, 0) == (NaN, 0, 0, 0) // for all representations of NaN
(-0, 0, 0, 0) == (+0, 0, 0, 0) // equal despite different bitwise representations
(1, 0, 0, 0) == (1, 0, 0, 0)
(0, 0, 0, 0) != (1, 0, 0, 0) // at least one different element => not equal …Run Code Online (Sandbox Code Playgroud) 我处理图像处理.我需要将16位整数SSE向量除以255.
我不能使用像_mm_srli_epi16()这样的移位运算符,因为255不是2的幂的倍数.
我当然知道可以将整数转换为浮点数,执行除法然后返回转换为整数.
但也许有人知道另一种解决方案......
我发现这个职位,说明如何进行转一个8x8矩阵的字节24点的操作,和几个卷轴后有代码实现转置.但是,这种方法没有利用我们可以阻止 8x8转置为4个4x4转置的事实,并且每个转换只能在一个shuffle指令中完成(这篇文章是参考文献).所以我推出了这个解决方案:
__m128i transpose4x4mask = _mm_set_epi8(15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0);
__m128i shuffle8x8Mask = _mm_setr_epi8(0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15);
void TransposeBlock8x8(uint8_t *src, uint8_t *dst, int srcStride, int dstStride) {
__m128i load0 = _mm_set_epi64x(*(uint64_t*)(src + 1 * srcStride), *(uint64_t*)(src + 0 * srcStride));
__m128i load1 = _mm_set_epi64x(*(uint64_t*)(src + 3 * srcStride), *(uint64_t*)(src + …Run Code Online (Sandbox Code Playgroud) 我尝试对 16 位整数 ARGB 通道的 64 位颜色的预乘进行矢量化。
我很快意识到,由于缺乏加速整数除法支持,我需要将我的值转换为float并显式使用一些 SSE2/SSE4.1 内在函数以获得最佳性能。尽管如此,我还是想保留非特定的通用版本作为后备解决方案(我知道它目前比某些普通操作慢,但它将提供未来可能的改进的兼容性)。
但是,在我的机器上结果不正确。
一个非常小的重现:
// Test color with 50% alpha
(ushort A, ushort R, ushort G, ushort B) c = (0x8000, 0xFFFF, 0xFFFF, 0xFFFF);
// Minimal version of the fallback logic if HW intrinsics cannot be used:
Vector128<uint> v = Vector128.Create(c.R, c.G, c.B, 0u);
v = v * c.A / Vector128.Create(0xFFFFu);
var cPre = (c.A, (ushort)v[0], (ushort)v[1], (ushort)v[2]);
// Original color:
Console.WriteLine(c); // prints (32768, 65535, 65535, 65535)
// Expected …Run Code Online (Sandbox Code Playgroud) 我试图将两个向量相乘,其中一个向量的每个元素乘以另一个向量的相同索引中的元素.然后,我想要对结果向量的所有元素求和,以获得一个数字.例如,对于矢量{1,2,3,4}和{5,6,7,8},计算结果如下:
1*5 + 2*6 + 3*7 + 4*8
基本上,我正在采用两个向量的点积.我知道有一个SSE命令来执行此操作,但该命令没有与之关联的内部函数.此时,我不想在我的C代码中编写内联汇编,所以我只想使用内部函数.这似乎是一个常见的计算,所以我很惊讶自己在Google上找不到答案.
注意:我正在针对特定的微架构进行优化,该架构最多支持SSE 4.2.
谢谢你的帮助.
有没有办法检查__m128i变量中的所有位/字节/字等是否为0?
在我的应用程序中,我必须检查__m128i变量中包含的所有整数是否为零.我是否必须提取它们并分别进行比较?
编辑:
int next = 0;
do{
//some code
next = idata.m128i_i32[0] + idata.m128i_i32[1] + idata.m128i_i32[2] + idata.m128i_i32[3];
}while(next > 0);
Run Code Online (Sandbox Code Playgroud)
我需要的是检查idata是否全为零而不必访问每个单独的元素,如果它们是...则退出循环...
基于Harold的评论,这是解决方案:
__m128i idata = _mm_setr_epi32(i,j,k,l);
do{
//some code
}while( !_mm_testz_si128(idata, idata) );
Run Code Online (Sandbox Code Playgroud)
如果idata中每个DW的所有低位都为0,这将退出循环...感谢hraold!
我有一个AVX CPU(不支持AVX2),我想计算两个256位整数的按位xor.
由于_mm256_xor_si256仅在AVX2上可用,我可以将这256位加载为__m256使用_mm256_load_ps,然后执行a _mm256_xor_ps.这会产生预期的结果吗?
我主要担心的是,如果内存内容不是有效的浮点数,_mm256_load_ps那么寄存器中的位不会与寄存器中的位完全相同吗?
谢谢.