使用SSE内在函数的简单的C ++程序编译(Compilation of a simple c++

2019-06-27 05:10发布

我是新来的SSE指令,我试图从该网站学习他们: http://www.codeproject.com/Articles/4522/Introduction-to-SSE-Programming

我使用的GCC编译器在Ubuntu 10.10采用Intel酷睿i7 960 CPU

下面是在此基础上,我试图文章代码:

对于长度的两个阵列ARRAY_SIZE它计算

fResult[i] = sqrt( fSource1[i]*fSource1[i] + fSource2[i]*fSource2[i] ) + 0.5

下面是代码

#include <iostream>
#include <iomanip>
#include <ctime>
#include <stdlib.h>
#include <xmmintrin.h> // Contain the SSE compiler intrinsics
#include <malloc.h>
void myssefunction(
          float* pArray1,                   // [in] first source array
          float* pArray2,                   // [in] second source array
          float* pResult,                   // [out] result array
          int nSize)                        // [in] size of all arrays
{
    int nLoop = nSize/ 4;

    __m128 m1, m2, m3, m4;

    __m128* pSrc1 = (__m128*) pArray1;
    __m128* pSrc2 = (__m128*) pArray2;
    __m128* pDest = (__m128*) pResult;


    __m128 m0_5 = _mm_set_ps1(0.5f);        // m0_5[0, 1, 2, 3] = 0.5

    for ( int i = 0; i < nLoop; i++ )
    {
        m1 = _mm_mul_ps(*pSrc1, *pSrc1);        // m1 = *pSrc1 * *pSrc1
        m2 = _mm_mul_ps(*pSrc2, *pSrc2);        // m2 = *pSrc2 * *pSrc2
        m3 = _mm_add_ps(m1, m2);                // m3 = m1 + m2
        m4 = _mm_sqrt_ps(m3);                   // m4 = sqrt(m3)
        *pDest = _mm_add_ps(m4, m0_5);          // *pDest = m4 + 0.5

        pSrc1++;
        pSrc2++;
        pDest++;
    }
}

int main(int argc, char *argv[])
{
  int ARRAY_SIZE = atoi(argv[1]);
  float* m_fArray1 = (float*) _aligned_malloc(ARRAY_SIZE * sizeof(float), 16);
  float* m_fArray2 = (float*) _aligned_malloc(ARRAY_SIZE * sizeof(float), 16);
  float* m_fArray3 = (float*) _aligned_malloc(ARRAY_SIZE * sizeof(float), 16);

  for (int i = 0; i < ARRAY_SIZE; ++i)
    {
      m_fArray1[i] = ((float)rand())/RAND_MAX;
      m_fArray2[i] = ((float)rand())/RAND_MAX;
    }

  myssefunction(m_fArray1 , m_fArray2 , m_fArray3, ARRAY_SIZE);

  _aligned_free(m_fArray1);
   _aligned_free(m_fArray2);
   _aligned_free(m_fArray3);

  return 0;
}

我收到以下错误compiltation

[Programming/SSE]$ g++ -g -Wall -msse sseintro.cpp 
sseintro.cpp: In function ‘int main(int, char**)’:
sseintro.cpp:41: error: ‘_aligned_malloc’ was not declared in this scope
sseintro.cpp:53: error: ‘_aligned_free’ was not declared in this scope
[Programming/SSE]$ 

我在哪里搞乱? 我失去了一些头文件? 我似乎已经包括所有相关的人。

Answer 1:

_aligned_malloc和_aligned_free是微软主义。 使用posix_memalign或memalign可在Linux 。 对于Mac OS X,你可以只使用malloc,因为它始终是16字节对齐。 对于便携式SSE代码,你通常要实现包装功能对齐的内存分配,例如,

void * malloc_simd(const size_t size)
{
#if defined WIN32           // WIN32
    return _aligned_malloc(size, 16);
#elif defined __linux__     // Linux
    return memalign(16, size);
#elif defined __MACH__      // Mac OS X
    return malloc(size);
#else                       // other (use valloc for page-aligned memory)
    return valloc(size);
#endif
}

实施free_simd就留给读者自己练习。



Answer 2:

简短的回答:使用_mm_malloc_mm_freexmmintrin.h而不是_aligned_malloc_aligned_free

讨论

应该使用_aligned_malloc_aligned_freeposix_memalignmemalign ,或任何其他当你写SSE / AVX代码。 这些都是编译器/平台特定的功能(或者MSVC或GCC或POSIX)。

Intel公司推出的功能_mm_malloc_mm_free在英特尔编译器专门用于SIMD计算(参见此 )。 其他编译器使用x86架构的目标加入他们太(就像他们经常添加英特尔内部函数)。 在这个意义上,他们是唯一的跨平台解决方案:他们应该在每一个编译器支持SSE是可用的。

这些功能在宣布xmmintrin.h头。 购买SSE / AVX版本的任何标头自动包括以前的,所以这将是足够的以仅包括smmintrin.hemmintrin.h例如。



Answer 3:

这并不直接回答你的问题,但我想指出的是您的SSE代码编写不当,我会感到惊讶,如果它的工作原理。 您需要在非SSE类型包括对齐非SSE类型喜欢你对齐float数组使用加载/存储操作(需要即使你有SSE类型的动态数组做到这一点)。 你需要时刻牢记的是,当你与SSE工作上证所数据类型假设在上证所表示数据寄存器和其他每一件事通常是在系统内存和非SSE寄存器,因此你需要从加载/存储/注册和存储。 该如何你的函数应该是这样的:

void myssefunction
(
    float* pArray1,                   // [in] first source array
    float* pArray2,                   // [in] second source array
    float* pResult,                   // [out] result array
    int nSize                         // [in] size of all arrays
)                                   
{
    const __m128 m0_5 = _mm_set_ps1(0.5f);        // m0_5[0, 1, 2, 3] = 0.5
    for (size_t index = 0; index < nSize; index += 4)
    {
        __m128 pSrc1 = _mm_load_ps(pArray1 + index); // load 4 elements from memory into SSE register
        __m128 pSrc2 = _mm_load_ps(pArray2 + index); // load 4 elements from memory into SSE register

        __m128 m1   = _mm_mul_ps(pSrc1, pSrc1);        // m1 = *pSrc1 * *pSrc1
        __m128 m2   = _mm_mul_ps(pSrc2, pSrc2);        // m2 = *pSrc2 * *pSrc2
        __m128 m3   = _mm_add_ps(m1, m2);                // m3 = m1 + m2
        __m128 m4   = _mm_sqrt_ps(m3);                   // m4 = sqrt(m3)
        __m128 pDest  = _mm_add_ps(m4, m0_5);          // pDest = m4 + 0.5

        _mm_store_ps(pResult + index, pDest); // store 4 elements from SSE register to memory.
    }
}

另外值得一提的是,你有多少个寄存器可以在给定的时间(像16 SSE2)使用的限制。 您可以编写代码,尝试用超过极限,但这将导致寄存器溢出。



文章来源: Compilation of a simple c++ program using SSE intrinsics
标签: c++ x86 sse simd