在我的 c++ builder 应用程序中包含 xmmintrin.h 的问题

Posted

技术标签:

【中文标题】在我的 c++ builder 应用程序中包含 xmmintrin.h 的问题【英文标题】:Problem including xmmintrin.h in my c++ builder application 【发布时间】:2020-07-31 19:14:37 【问题描述】:

我正在尝试编写一些 SIMD 代码(在 C++Builder 10.1 Berlin 中),但在 mmintrin.h 中出现 E2257 错误(包含在 xmmintrin.h 中,应该包含在SIMD 的东西)。有一堆相同的错误,所以 bcc32 似乎无法处理这些标头中的语法。

例如,所有包含__atribute__ 的行似乎都会导致此错误:

typedef long long __m64 __attribute__((__vector_size__(8)));

对我来说,这似乎是一个 C++builder 错误,但我不确定,老实说我不熟悉 __atribute__(这似乎不是 C++ 关键字,所以我假设它是函数/宏或语言扩展)。

更新:由于 C++ Builder 10.1 Berlin 可以使用 Clang (bcc32c 而不是旧编译器 bcc32) ,我也尝试过,这有助于消除所有 E2257 错误。不幸的是,我现在得到一个 ICE( [bcc32c Error] FillObj.cpp(1): ICE: Internal compiler error: C0000005 @ 27287E3D )。罪魁祸首是这一行_mm_storeu_ps(&a[i], xmm0 ); 注释掉这一行会使代码编译。此代码只是一个示例,但足以重现问题。

#include <xmmintrin.h>

void SumValues(float * a, float * b, unsigned len)

    __m128 xmm0, xmm1;
    //for this simple example , it's assumed len is divisible by     
    for(int i=0; i<len; i += 4)

      xmm0 = _mm_loadu_ps( &a[i] );
      xmm1 = _mm_loadu_ps( &b[i] );

      xmm0 = _mm_add_ps(xmm0, xmm1);

      _mm_storeu_ps( &a[i], xmm0 );//this line is causing the ICE described above

    

正如我在评论中所说,这在 Qt 中运行良好(使用 MinGw 5.5.0 )。关于 Clang 编译器,我不确定它是哪个版本,但由于它必须支持所有 VCL 东西,我认为它不是标准的 clang 编译器。

【问题讨论】:

该语法是 GNU C 扩展 (gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html)。每个编译器通常都有自己的头文件版本,例如MSVC 看起来一点也不像(而不是使用结构的联合)。您是否手动使用 GCC 的 xmmintrin.h 和 bcc32?您确定 bcc32 甚至完全支持 SSE 代码生成吗? community.idera.com/developer-tools/general-development/f/… 确实说有一个 -mmmx 命令行选项也可能启用 SSE。 您在 C++ Builder(柏林版)文档的哪个位置阅读了有关 __attribute__ 的信息? @Peter Cordes,我不确定 bcc32 是否支持 SSE,但是这两个头文件与 C++ builder 捆绑在一起,所以这是我的假设(这不是特定于 C++ builder berlin,这些头文件一直是只要我记得,它就是 c++ builder 安装的一部分)。 @Eljay,看看我对彼得的评论。 clang/LLVM 对 GNU C 扩展没有问题,包括对向量扩展使用相同的语法。如果您可以使用像 clang 这样的优秀现代编译器,那就去做吧!如果您想假设 SSE3 和其他相当老的扩展作为基线,最好使用 -march=pentium-m -mtune=haswell 或类似的东西。 【参考方案1】:

我在 IDE 中使用了 10.4 Sydney 64 位 Windows C++ 编译器,您的示例为我编译和执行。

void SumValues(float * a, float * b, unsigned len)
    __m128 xmm0, xmm1;
    //for this simple example , it's assumed len is divisible by
    for(int i=0; i<len; i += 4)

      xmm0 = _mm_loadu_ps( &a[i] );
      xmm1 = _mm_loadu_ps( &b[i] );
      xmm0 = _mm_add_ps(xmm0, xmm1);
      _mm_storeu_ps( &a[i], xmm0 );//this line is causing the ICE described above
    


__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)


//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)

    //
    float myA[4],myB[4];
    myA[0] = 0.0;
    myA[1] = 1.0;
    myA[2] = 2.0;
    myA[3] = 3.0;
    myB[0] = 0.0;
    myB[1] = 1.0;
    myB[2] = 2.0;
    myB[3] = 3.0;
    SumValues(myA,myB,4);
    Button1->Caption = FloatToStr(myA[2]);

【讨论】:

看来问题在 C++ 10.4 Sydney 中得到了解决。 我在 10.4 的源代码中发现了以下 IFDEF:#if defined(clang) #if (clang_major == 5 && clang_minor == 0) #include #elif (clang_major == 3 && clang_minor == 3) #include #else #error "无法确定正确的 clang 头版本" #endif #else #error "仅支持 clang 编译器" #endif 那些 ifdef 在 10.1 Berlin 中不存在(至少我没有看到它们),所以我可以假设它们是在更新版本的编译器中添加的。 Embarcadero 的一名员工(就在昨天通过电子邮件)还告诉我,只有 64 位 Clang 编译器支持 SSE 内容。 32 位编译器仍然通过 FPU 传递值(他没有说明原因)。这也许可以解释为什么您设法让我的示例正常工作。 在 10.4 Sydney 中,带有 xmmintrin.h 的 clang 的 ifdef 可以在 C:\Program Files (x86)\Embarcadero\Studio\21.0\include\windows\crtl\xmmintrin.h 中找到

以上是关于在我的 c++ builder 应用程序中包含 xmmintrin.h 的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在应用程序中包含 Visual C++ 再分发

在 cmake c++ 项目中包含库的首选方法是啥?

如何在 MongoDb 驱动程序的列表中包含特定字段

在 C++ 中包含来自单独文件夹的文件

在 Netbeans 7.0 中包含 C++ 库

如何在我的 svg 中包含一个很棒的字体图标?