c - 学习使用内在函数——使用 _mm256_sub_ps 的段错误

标签 c vectorization intel intrinsics

我正在尝试学习如何使用内部函数。 所以,我的 C 代码是:

void Vor(

    const int NbPoints,
    const int height,
    const int width,
    float * X,
    float * Y,
    int   * V,
    int   * const ouVor )
{

    float Xd , Yd;
    float Distance ,initDistance = FLT_MAX;
    int Threshold;

    int x , y; // pixel coordinates
    int i;

    for ( y = 0; y < height; y++ )
    {
        for ( x = 0; x < width; x++ )
        {
            for ( i = 0; i < NbPoints; i++ )
            {
                Xd = X[ i ] - x;
                Yd = Y[ i ] - y;
                Distance = Xd * Xd + Yd * Yd;

                //if this Point is closer , assign proper threshold
                if ( Distance < initDistance )
                {
                    initDistance = Distance;
                    Threshold = V[ i ];
                }

                *( ouVor + ( x + y * width ) ) = Threshold;

            } /* i */
        } /* x */

    } /* y */


}

现在,使用 openMP 和内在函数。我正在做:

void Vor(

    const  int  NbOfPoints,
    const  int  height,
    const  int  width,
    float * restrict X,
    float * restrict Y,
    int   * restrict V,
    int   * restrict ouVor )
{


    __m128 Xd , Yd;

    __m128i Threshold;
    int x , y; // pixel coordinates
    float initDistance = FLT_MAX;

    float * TempDistance = (float*) _mm_malloc( NbOfPoints * sizeof(*TempDistance) ,64 );

    __m128 * SIMDTempDistance = (__m128*) TempDistance;
    __m128 * theX = (__m128*) X;
    __m128 * theY = (__m128*) Y;
    __m128i * theV = (__m128i*) V;
    __m128i * theVor = (__m128i*) ouVor;


        #pragma omp parallel for default( none ) shared( X , Y , V , ouVor ,height , width ,NbOfPoints ) private ( x,y,Xd,Yd,TempDistance ,Threshold ) collapse(2)  
    for ( y = 0; y < height; y++ )
    { 
        for ( x = 0; x < width; x++ )
        {

            __m128 Distance = _mm_load_ps( &initDistance );

            for ( int i = 0; i < NbOfPoints; i++ )
            {
                Xd = _m128_sub_ps( theX[ i ] , x );
                Yd = _m128_sub_ps( theY[ i ] , y );
                SIMDTempDistance[ i ] = _m128_add_ps( Xd * Xd , Yd * Yd );

                __m128 theMin = _m128_gmin_ps( SIMDTempDistance , &Distance );

                Distance = theMin;
                Threshold = theV[ i ];

                } /* i */

                //write result
                *( ouVor + x + y * width ) = Threshold;

            } /* x */

        } /* y */


    _mm_free( TempDistance );

}

我收到一些错误,例如:

function "_m128_sub_ps" declared implicitly
Xd = _m128_sub_ps( theX[ i ] , x );

error: a value of type "int" cannot be assigned to an entity of type "__m128"
Xd = _m128_sub_ps( theX[ i ] , x );

a value of type "__m128i" cannot be assigned to an entity of type "int"
*( ouVor + x + y * width ) = Threshold

(和 Yd 、theMin 、SIMDTempDistance 相同的错误)

我怎样才能克服这些问题?

此外,我删除了 if 语句并使用 _m128_gmin_ps 找到最小值。我的实现是否正确?

------------更新----------------

在 Sourav Ghosh 发表评论后,我搜索了标题。 我找不到 128 位的任何地方,所以我使用 256 位使用 #include <immintrin.h>

在更正几行之后:

__m256 Distance = _mm256_load_ps( &intiDistance );

__m256 theMin = _mm256_min_ps( SIMDTempDistance[ i ] , &Distance );

以及对 _mm256 而不是 _m256 的所有函数调用,我只收到这些错误:

error: argument of type "int" is incompatible with parameter of type "__m256"
Xd = _mm256_sub_ps( theX[ i ] , x );
Yd = _mm256_sub_ps( theY[ i ] , y );

x 和 y 是整数并在循环中使用。我不知道如何克服这个问题。

-----更新--------------------

我想!我正在类型转换.. 我用过:

__m256i xxIdx = _mm256_set1_epi32( x );
__m256  xIdx  = _mm256_castsi256_ps( xxIdx );

现在,我的代码是:

void Vor(

        const  int  NbOfPoints,
        const  int  height,
        const  int  width,
        float * restrict X,
        float * restrict Y,
        int   * restrict V,
        int   * restrict ouVor )
    {



       __m256 Xd , Yd;

       __m256i Threshold;
        int x , y; // pixel coordinates


        float * TempDistance = (float*) _mm_malloc( NbOfPoints * sizeof(*TempDistance) ,64 );

        __m256 * SIMDTempDistance = (__m256*) TempDistance;
        __m256 * theX = (__m256*) X;
        __m256 * theY = (__m256*) Y;
        __m256i * theV = (__m256i*) V;
        __m256i * theVor = (__m256i*) ouVor;


    #pragma omp parallel for default( none ) shared( X , Y , V , ouVor ,height , width ,NbOfPoints ,ouVor ,theX,theY,theV ) private ( x,y,Xd,Yd,TempDistance ,Threshold,SIMDTempDistance ) collapse(2)  

    for ( y = 0; y < height; y++ )
    { 
        for ( x = 0; x < width; x++ )
        {
                float initDistance = FLT_MAX;
                __m256 Distance = _mm256_set1_ps( initDistance );

                for ( int i = 0; i < NbOfPoints; i++ )
                {
                    __m256i xxIdx = _mm256_set1_epi32( x );
                    __m256  xIdx  = _mm256_castsi256_ps( xxIdx );

                    __m256i yyIdx = _mm256_set1_epi32( y );
                    __m256  yIdx  = _mm256_castsi256_ps( yyIdx );

                    Xd = _m256_sub_ps( theX[ i ] , xIdx );
                    Yd = _m256_sub_ps( theY[ i ] , yIdx );
                    SIMDTempDistance[ i ] = _m256_add_ps( Xd * Xd , Yd * Yd );

                    __m256 theMin = _m256_gmin_ps( SIMDTempDistance , Distance );

                    Distance = theMin;
                    Threshold = theV[ i ];

                    } /* i */

                    //write result
                    *( ouVor + x + y * width ) = Threshold;

                } /* x */

            } /* y */


        _mm_free( TempDistance );

    }

我这样编译:

icc -std=c99 -g -openmp -qopt-report=2 -o mycode mycode.c

没关系。

但是运行代码会出现段错误..

在线:

Xd = _m256_sub_ps( theX[ i ] , xIdx );
Yd = _m256_sub_ps( theY[ i ] , yIdx );

最佳答案

我认为,您缺少一些包含 _m128_sub_ps() 函数前向声明的必需头文件。我们可以假设 _m128_sub_ps() 函数的返回类型为 __m128,但如果没有适当的前向声明,编译器会假设默认 _m128_sub_ps() 函数的返回类型为 int。这就是为什么编译器发出

function "_m128_sub_ps" declared implicitly

然后,int 返回值被分配给类型为 __m128 的变量,从而产生了问题。


编辑:

根据修改后的代码,

int x , y; // pixel coordinates

应该是

__m256 x , y; // pixel coordinates

作为signature of _mm256_sub_ps()要求两个参数都是 __m256

类型

关于c - 学习使用内在函数——使用 _mm256_sub_ps 的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29489783/

相关文章:

c - 指针参数警告

c - C 中的动态连续 3D 数组

matlab - Octave:如何对这些 FOR 循环进行矢量化?

performance - 为什么矢量化通常比循环更快?

gcc - 为 GCC 的矢量扩展加载数据

multithreading - 混合SIMD指令和多线程时,我会受到性能损失吗?

c - 如何检查索引是否包含符号?

c - 添加到 from 目录的链表数组

c++ - 是否可以在单个命令中存储 8 个字节

c - Intel Intrinsics 的段错误