如何将参数传递给英特尔 SSE 内在函数中的 const 值?
Posted
技术标签:
【中文标题】如何将参数传递给英特尔 SSE 内在函数中的 const 值?【英文标题】:how to pass parameters to const value in intel SSE intrinsics? 【发布时间】:2014-02-01 20:55:12 【问题描述】:我知道在参数中使用 const value ;当您不希望函数修改参数时。
所以这个测试代码运行良好:
#include "stdafx.h"
#include <io.h>
#include <iostream>
using namespace std;
void foo (const int y )
printf ( "x = %d \n" , y*2 ) ;
int _tmain(int argc, _TCHAR* argv[])
int y = 3;
foo ( y );
system("pause");
return 0;
但是当我在英特尔 SSE 内在函数(例如 *_mm_blend_epi16* 函数)上执行相同操作时,我收到此错误:
error C2057: expected constant expression
这个错误的代码是:
#include "stdafx.h"
#include <io.h>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
int y = 3 ;
__m128i x1,x2;
_mm_blend_epi16(x1,x2,y);
system("pause");
return 0;
而_mm_blend_epi16的定义是:
__m128i _mm_blend_epi16( __m128i a, __m128i b, const int mask )
那么,问题是什么?难道我做错了什么 ?
编辑解决办法是什么?
【问题讨论】:
请注意,这确实适用于 gcc(使用 gcc 4.5.2 和 gcc 4.8.2 测试)。 Microsoft Visual Studio 2012 失败。 @ScottD 第一个代码在 Visual c++ 2012 中运行良好。问题出在给我上述错误的第二个代码中 我明白了。我只是指出这个问题是特定于 Microsoft 编译器的,而不是一般的 C 或 C++ 编译器。也就是说,第二个代码使用 gcc。 不可能做你想做的事 -mask
参数是一个立即操作数 - 这意味着它是指令的一部分并且必须在编译时知道。如果您需要一个单独的函数来调用带有掩码作为参数的 _mm_blend_epi16,则必须将其实现为宏并在任何地方编写类似 const int mask = 3
的代码。或者,您可以使用类似的指令_mm_blendv_epi8
对 8 位字进行洗牌,并且不需要掩码是编译时常量(请注意,它必须与 _mm_blend_epi16
的掩码略有不同。
【参考方案1】:
问题在于_mm_blend_epi16
不仅要求掩码为const int
,而且还需要在编译时为已知值(如c++11 中的constexpr
)。所以,即使_mm_blend_epi16(x1,x2,(const int)y)
也行不通。此行为与测试示例中的行为不同,因为它是编译器内在函数,而不是真正的函数。
【讨论】:
嗨!您在内容方面写得很好,但请阅读格式常见问题解答。谢谢。【参考方案2】:这是一个可能有用的解决方法。限制:所需的高效代码生成仅存在于发布(优化)构建中。如果编译器无法确定掩码值,则不会记录错误消息。相反,您将获得低效的代码生成。因此,必须使用调试器或反汇编器检查代码生成以确认所需的结果。此解决方法需要调用包装函数来代替 _mm_blend_epi16 本身。优化器将在其位置内联单个 _mm_blend_epi16。这是一个使用纯 C 代码的示例。使用 Visual Studio 2010 和 Visual Studio 2013 测试。
#include "stdio.h"
#include "smmintrin.h"
#define XM(a,b,x) if (mask == x) result = _mm_blend_epi16 (a, b, x)
#define XM1(a,b,x) XM (a,b,x+0x00); XM (a,b,x+0x01); XM (a,b,x+0x02); XM (a,b,x+0x03);\
XM (a,b,x+0x04); XM (a,b,x+0x05); XM (a,b,x+0x06); XM (a,b,x+0x07);\
XM (a,b,x+0x08); XM (a,b,x+0x09); XM (a,b,x+0x0A); XM (a,b,x+0x0B);\
XM (a,b,x+0x0C); XM (a,b,x+0x0D); XM (a,b,x+0x0E); XM (a,b,x+0x0F);
static __m128i my_mm_blend_epi16(__m128i a, __m128i b, int mask)
__m128i result;
XM1 (a, b, 0x00); XM1 (a, b, 0x10); XM1 (a, b, 0x20); XM1 (a, b, 0x30);
XM1 (a, b, 0x40); XM1 (a, b, 0x50); XM1 (a, b, 0x60); XM1 (a, b, 0x70);
XM1 (a, b, 0x80); XM1 (a, b, 0x90); XM1 (a, b, 0xa0); XM1 (a, b, 0xb0);
XM1 (a, b, 0xc0); XM1 (a, b, 0xd0); XM1 (a, b, 0xe0); XM1 (a, b, 0xf0);
return result;
int main(void)
int y = 0x99;
__m128i x1,x2;
x1 =_mm_set_epi32 (1, 2, 3, 4);
x2 =_mm_set_epi32 (5, 6, 7, 8);
x2 = my_mm_blend_epi16 (x1, x2, y);
printf ("%x\n", _mm_cvtsi128_si32 (x2));
return 0;
这是显示代码生成的发布构建调试器视图:
int main(void)
00161000 55 push ebp
00161001 8B EC mov ebp,esp
00161003 83 E4 F8 and esp,0FFFFFFF8h
int y = 0x99;
__m128i x1,x2;
x1 =_mm_set_epi32 (1, 2, 3, 4);
00161006 66 0F 6F 05 00 21 16 00 movdqa xmm0,xmmword ptr ds:[162100h]
x2 =_mm_set_epi32 (5, 6, 7, 8);
0016100E 66 0F 6F 0D 10 21 16 00 movdqa xmm1,xmmword ptr ds:[162110h]
x2 = my_mm_blend_epi16 (x1, x2, y);
00161016 66 0F 3A 0E C1 99 pblendw xmm0,xmm1,99h
printf ("%x\n", _mm_cvtsi128_si32 (x2));
0016101C 66 0F 7E C0 movd eax,xmm0
00161020 50 push eax
00161021 68 F4 20 16 00 push offset string "%x\n" (1620F4h)
00161026 FF 15 A0 20 16 00 call dword ptr [__imp__printf (1620A0h)]
0016102C 83 C4 08 add esp,8
return 0;
0016102F 33 C0 xor eax,eax
【讨论】:
【参考方案3】:内在
__m128i _mm_blend_epi16( __m128i a, __m128i b, const int mask
期望第三个参数是一个 const int;所以一个在编译时已知的 const 值。
如果你修改如下代码:
const int y = 3 ;
_mm_blend_epi16(x1,x2,y);
如果应该可以。
或者,使用#define
作为掩码
【讨论】:
以上是关于如何将参数传递给英特尔 SSE 内在函数中的 const 值?的主要内容,如果未能解决你的问题,请参考以下文章