【问题标题】:Intrinsics program (SSE) - g++ - help needed内在程序 (SSE) - g++ - 需要帮助
【发布时间】:2011-02-24 01:46:12
【问题描述】:

这是我第一次在 stackoverflow 上发布问题,所以请尝试忽略我在格式化问题/代码时可能犯的任何错误。但是请务必向我指出同样的问题,这样我可能会更加小心。

我试图编写一些简单的内在函数例程来添加两个 128 位(包含 4 个浮点变量)数字。我在网上找到了一些代码,并试图让它在我的系统上运行。代码如下:

 //this is a sample Intrinsics program to add two vectors.

    #include <iostream>  
    #include <iomanip>      
    #include <xmmintrin.h>  
    #include <stdio.h>

    using namespace std;

    struct vector4 {  
        float x, y, z, w;    };   

    //functions to operate on them.  
    vector4 set_vector(float x, float y, float z, float w = 0) {     
        vector4 temp;  
        temp.x = x;   
        temp.y = y;   
        temp.z = z;  
        temp.w = w;  
        return temp;  
    }    


    void print_vector(const vector4& v) {   
        cout << " This is the contents of vector: " << endl;  
        cout << " > vector.x = " << v.x << endl;  
        cout << " vector.y = " << v.y << endl;  
        cout << " vector.z = " << v.z << endl;  
        cout << " vector.w = " << v.w << endl;  
    }

    vector4 sse_vector4_add(const vector4&a, const vector4& b) {  
        vector4 result;  

        asm volatile (  
          "movl $a, %eax" //move operands into registers.  
          "\n\tmovl $b, %ebx"  
          "\n\tmovups  (%eax), xmm0"  //move register contents into SSE registers.  
          "\n\tmovups (%ebx), xmm1"  
          "\n\taddps xmm0, xmm1" //add the elements. addps operates on single-precision vectors.    
          "\n\t movups xmm0, result" //move result into vector4 type data.  
        );
        return result;  
    }

    int main() {     
        vector4 a, b, result;  
        a = set_vector(1.1, 2.1, 3.2, 4.5);   
        b = set_vector(2.2, 4.2, 5.6);    
        result = sse_vector4_add(a, b);    
        print_vector(a);  
        print_vector(b);    
        print_vector(result);
        return 0;
    }

我使用的g++参数是:

g++ -Wall -pedantic -g -march=i386 -msse intrinsics_SSE_example.C -o h

我得到的错误如下:

intrinsics_SSE_example.C: Assembler messages:  
intrinsics_SSE_example.C:45: Error: too many memory references for movups  
intrinsics_SSE_example.C:46: Error: too many memory references for movups  
intrinsics_SSE_example.C:47: Error: too many memory references for addps  
intrinsics_SSE_example.C:48: Error: too many memory references for movups  

我花了很多时间尝试调试这些错误,搜索它们等等。我是内在学的完全菜鸟,因此可能忽略了一些重要的事情。

感谢您的帮助,
谢谢,
斯里拉姆。

【问题讨论】:

  • 要格式化代码,请使用工具栏上的“1010”按钮(缩进 4 个空格)。不要&lt;blockquote&gt;他们。
  • 感谢 KennyTM。我已经做出了改变。

标签: g++ inline-assembly sse intrinsics


【解决方案1】:

您使用的是 ASM 块,而不是内在的。

由于这些 xmmX 是寄存器,您应该在它们前面加上 %:

      "\n\tmovups  (%eax), %xmm0"
      // etc.

您的 ASM 有几个错误。

  1. 您不应修改ebx 寄存器。
  2. $a 等在汇编程序中被视为全局符号,但事实并非如此。
  3. addps %xmm0, %xmm1 会将结果存储到 xmm1 中。请记住,在 AT&T 语法中,目的地位于右侧。

修正后的 ASM 块是这样的

    asm volatile (  
      "movl %1, %%eax"
      "\n\tmovl %2, %%ecx"  
      "\n\tmovups  (%%eax), %%xmm0"
      "\n\tmovups (%%ecx), %%xmm1"  
      "\n\taddps %%xmm0, %%xmm1"
      "\n\tmovups %%xmm0, %0"
      : "=m"(result)
      : "r"(&a), "r"(&b)
      : "eax", "ecx");

基本上,%0 将替换为result 的地址,%1 和%2 将替换为&amp;a&amp;b。有关详细说明,请参阅http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html"eax", "ecx" 防止这 2 个寄存器被用作那些 %n 的替换。

但前 2 个movl 是不必要的......

    asm volatile(  
      "\n\tmovups (%1), %%xmm0"
      "\n\tmovups (%2), %%xmm1"  
      "\n\taddps %%xmm1, %%xmm0"
      "\n\tmovups %%xmm0, %0"
      : "=m"(result)
      : "r"(&a), "r"(&b));

既然你提到了内在,为什么不使用__builtin_ia32_addps

【讨论】:

  • /tmp/ccXM3Fog.o:在函数sse_vector4_add(vector4 const&amp;, vector4 const&amp;)': /intrinsics_SSE_example.C:43: undefined reference to a' /intrinsics_SSE_example.C:43:未定义引用b' /intrinsics_SSE_example.C:43: undefined reference to xmm0' /intrinsics_SSE_example.C:43:未定义引用“结果” collect2: ld 返回 1 个退出状态
  • 哇!做到了。我一直在浏览您提到的文档,但我想我还不够彻底。我有一个问题:这与内在函数不同吗?每当我在网上阅读有关相同内容的文档时,它都会说内在函数是使用我上面使用的指令在 C/C++ 程序中使用内联汇编代码的一种方式。我说的对吗?
  • @Siriam:见en.wikipedia.org/wiki/Intrinsic_function。 ASM 块不是函数。
  • SSE en.wikipedia.org/wiki/Streaming_SIMD_Extensions 的维基百科条目提到了添加 2 个向量的示例。他们使用我上面使用的相同指令(在伪代码中)。我需要做什么才能将此代码“转换”为内部函数?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-27
  • 2011-05-09
  • 2011-08-06
  • 1970-01-01
  • 2014-08-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多