代码之家  ›  专栏  ›  技术社区  ›  Brett

为什么我的数据看起来不一致?

  •  4
  • Brett  · 技术社区  · 15 年前

    在我的程序开始时,我创建了一个成员为的对象:

    static __m128 *m_sincos;
    

    然后在构造函数中初始化该成员:

    m_sincos = (__m128*) _aligned_malloc(Bins*sizeof(__m128), 16);
    for (int t=0; t<Bins; t++)
      m_sincos[t] = _mm_set_ps(cos(t), sin(t), sin(t), cos(t));
    



    当我使用m\u sincos时,我遇到了三个问题:

    movaps xmm0, m_sincos[t] //crashes
    movups xmm0, m_sincos[t] //does not crash
    

    -变量似乎不正确

    movaps result, xmm0 // returns values that are not what is in m_sincos[t]
    //Although, putting a watch on m_sincos[t] displays the correct values
    

    -真正让我困惑的是,这让一切都正常(但太慢了):

    __m128 _sincos = m_sincos[t];
    movaps xmm0, _sincos
    movaps result, xmm0
    
    2 回复  |  直到 8 年前
        1
  •  10
  •   Oren Trutner    15 年前

    m_sincos[t] 是一个C表达式。然而,在装配说明中( __asm

    movaps xmm0, m_sincos[t]
    

    movaps xmm0, xmmword ptr [t]
    

    该解释试图复制存储在变量地址处的128位值 t 进入xmm0。 t型 但是,是可能未对齐地址处的32位值。执行该指令很可能会导致对齐失败,并且在异常情况下会得到不正确的结果,其中 t型

    您可以通过使用适当的x86寻址模式来解决这个问题。下面是缓慢但清晰的版本:

    __asm mov eax, m_sincos                  ; eax <- m_sincos
    __asm mov ebx, dword ptr t
    __asm shl ebx, 4                         ; ebx <- t * 16 ; each array element is 16-bytes (128 bit) long
    __asm movaps xmm0, xmmword ptr [eax+ebx] ; xmm0 <- m_sincos[t]
    

    旁注:

    当我把它放到一个完整的程序中时,会发生一些奇怪的事情:

    #include <math.h>
    #include <tchar.h>
    #include <xmmintrin.h>
    
    int main()
    {
        static __m128 *m_sincos;
        int Bins = 4;
    
        m_sincos = (__m128*) _aligned_malloc(Bins*sizeof(__m128), 16);
        for (int t=0; t<Bins; t++) {
            m_sincos[t] = _mm_set_ps(cos((float) t), sin((float) t), sin((float) t), cos((float) t));
            __asm movaps xmm0, m_sincos[t];
            __asm mov eax, m_sincos
            __asm mov ebx, t
            __asm shl ebx, 4
            __asm movaps xmm0, [eax+ebx];
        }
    
        return 0;
    }
    

    当你运行这个程序时,如果你一直盯着registers窗口,你可能会发现一些奇怪的东西。虽然结果是正确的, xmm0 这个 movaps 指令被执行。怎么会这样?

    查看生成的汇编代码可以发现 _mm_set_ps() 将sin/cos结果加载到 xmm0型 穆辛科斯 . 但价值仍然存在 xmm0型 我也是。 _mm_set_ps 是“内在的”,不是函数调用;完成后,它不会尝试还原它使用的寄存器的值。

        2
  •  1
  •   Puppy    15 年前

    您应该始终使用instrinsic,甚至只打开并保留它们,而不是显式地将其编码进来。这是因为asm不能移植到64位代码。

    推荐文章