使用 __m64 引用将 C++ 项目转换为 x64

Posted

技术标签:

【中文标题】使用 __m64 引用将 C++ 项目转换为 x64【英文标题】:Converting a C++ project to x64 with __m64 references 【发布时间】:2015-09-07 21:12:59 【问题描述】:

因此,当我开始转换并将目标设置为“x64”时,我得到了 7 个未解决的外部变量。两个例子:

error LNK2001: unresolved external symbol _m_empty    ...CONVOLUTION_2D_USHORT.obj  CONVOLUTION_2D_USHORT
error LNK2001: unresolved external symbol _mm_setzero_si64  ...CONVOLUTION_2D_USHORT.obj    CONVOLUTION_2D_USHORT

所以我尝试对这些进行更深入的调查,发现它不喜欢头文件中的 __m64:特别是 mmintrin.h(可能还有其他文件)。在我使用 C++ 的业余时间里,因为我已经好几年没有弄乱这门语言了(我通常在 C# 部门),我试图编辑头文件,并将 __m64 替换为 __m128i ??!!。不知道什么是正确的路线,让这个和其他 DLL 编译 MachineX64。在编辑并将标头的源代码放在我的本地目录中之后,它仍然不允许我通过右键单击...再次编译 - 业余时间。 有几个人问过类似的问题,但我找不到适合我的问题。

这是一个带有不受支持的 __m64 的“mmintrin.h”示例...

typedef union __declspec(intrin_type)_CRT_ALIGN(8) __m64

unsigned __int64    m64_u64;
float               m64_f32[2];
__int8              m64_i8[8];
__int16             m64_i16[4];
__int32             m64_i32[2];
__int64             m64_i64;
unsigned __int8     m64_u8[8];
unsigned __int16    m64_u16[4];
unsigned __int32    m64_u32[2];
 __m64;

/* General support intrinsics */
void  _m_empty(void);
__m64 _m_from_int(int _I);
int   _m_to_int(__m64 _M);
__m64 _m_packsswb(__m64 _MM1, __m64 _MM2);
__m64 _m_packssdw(__m64 _MM1, __m64 _MM2);
__m64 _m_packuswb(__m64 _MM1, __m64 _MM2);
__m64 _m_punpckhbw(__m64 _MM1, __m64 _MM2);
__m64 _m_punpckhwd(__m64 _MM1, __m64 _MM2);
__m64 _m_punpckhdq(__m64 _MM1, __m64 _MM2);
__m64 _m_punpcklbw(__m64 _MM1, __m64 _MM2);
__m64 _m_punpcklwd(__m64 _MM1, __m64 _MM2);
__m64 _m_punpckldq(__m64 _MM1, __m64 _MM2);
...

【问题讨论】:

你得到了 2 个未解决的外部问题还是 7 个? 7.. !drive.google.com/file/d/0B3qrpuwM39vmM1lGazR2WWhRamM/… 【参考方案1】:

来自__m64 类型文档:

x64 处理器不支持 __m64 数据类型。使用 __m64 作为 MMX 内部函数的一部分的应用程序必须重写以使用等效的 SSE 和 SSE2 内部函数。

http://msdn.microsoft.com/en-us/library/08x3t697(v=vs.110).aspx

所以看起来您有三个选择:坚持使用 32 位,将 MMX 内在函数移植到 SSE,或回退到非 SIMD 实现(如果有 - 如果没有,请考虑在标量代码中重新实现) .

【讨论】:

@RobertKoernke:内在函数在非常低的抽象级别上运行——不存在为所有 MMX 操作提供精确等价物的映射。您是否知道更高的抽象级别 valarray 现在已在 C++ 中标准化? 任何内部使用__m64 类型的东西都是MMX 或3DNow!因此不推荐用于 x64 本机。希望代码库具有您可以依赖的内在优化函数的 C++ 实现,但无论哪种方式,您都必须将 MMX 重新实现为 SSE 以实现可移植性。好消息是,一旦你这样做了,它仍然可以为 x86 和 x64 本机构建。 它是可移植的,因为相同的 SSE 内在函数将为 x86 和 x64 本机编译(即,您不需要为 x86 和 x64 本机维护不同的代码路径)。如今,SSE/SSE2 支持无处不在。这些事实大量用于DirectXMath。显然,它们不会针对 ARM 或 PPC 等其他架构进行编译,因此内部优化代码应该有一个标准的 C/C++ 代码路径作为后备维护,以提高可移植性。 @RobertKoernke:使用可以编译使用 MMX(带有内在函数)的 64 位代码的编译器。例如,gcc 对 #include <mmintrin.h> void emms(void) _m_empty(); 没有问题 virtualdub.org/blog/pivot/entry.php?id=107 表示 MMX 在 64 位 Windows 应用程序中可用。因此,如果您遇到问题,那是您的编译器的错。有时将 MMX 代码移植到 SSE 很容易,甚至会加快速度。其他时候,这意味着您必须调整调用代码以并行执行两个 8x8 SAD 或其他操作。 (例如 ffmpeg 的 mpdecimate 过滤器) @RobertKoernke:用你目前拥有的代码提出一个新问题。未对齐的 SSE 内存访问错误,除非您使用未对齐的加载内在函数之一 (_mm_loadu_si128)。 AVX 恢复了该决定,并允许未对齐的地址,但对齐的加载/存储内在函数除外。我仍然很惊讶在使用 Visual C++ 的项目中没有一种合理的方法来编译 MMX 内在函数。也许您可以使用 gcc 或 clang 编译您的 MMX 代码,并将其链接到您的 Visual C++ 项目?你可能会。需要extern "C"函数,因为不同的名称修改。

以上是关于使用 __m64 引用将 C++ 项目转换为 x64的主要内容,如果未能解决你的问题,请参考以下文章

int64_t 指针转换为 AVX2 内在 _m256i

如何将两个_pd 转换为一个_ps?

将图像从 CV_64F 转换为 CV_8U

将 __m256i 寄存器转换为 uint64_t 位掩码,以便每个字节值处的值是输出中的设置位

AVX 将 64 位整数转换为 64 位浮点数

防止将 uint64_t 转换为 uint16_t