【问题标题】:learning to use intrinsics -- segm fault using _mm256_sub_ps学习使用内在函数——使用 _mm256_sub_ps 的段错误
【发布时间】:2015-06-11 22:38:21
【问题描述】:

我正在尝试学习如何使用内在函数。 所以,我的 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 位,所以我使用 #include &lt;immintrin.h&gt; 使用 256 位

将几行更正为:

__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 );

【问题讨论】:

    标签: c vectorization intel intrinsics


    【解决方案1】:

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

    函数“_m128_sub_ps”隐式声明

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


    编辑:

    根据修改后的代码,

    int x , y; // pixel coordinates
    

    应该是

    __m256 x , y; // pixel coordinates
    

    因为signature of _mm256_sub_ps() 要求两个参数都是__m256 类型

    【讨论】:

    • @George _m128_sub_ps()的函数原型是什么?它在 中吗?
    • :我已经尝试过了,但是它在循环所在的行中给出了很多错误。例如,错误:“int”类型的值不能分配给类型的实体"__m256" for ( y = 0; y
    • @George 好吧,我不确定,但您可以使用Xd = _mm256_sub_ps( theX[ i ] , (__m256) x ); 之类的东西绕过警告。但是,我不确定这是否是您想要的。请确认。
    • 它给出:不允许强制转换为“__m256”类型
    【解决方案2】:

    你对内在名称有点糊涂了。

    对于 128 位 SSE,它只是,例如:

    _mm_sub_ps
    

    不是:

    _mm128_sub_ps
    

    [混淆可能是因为使用 256 位 AVX 它是_mm256_sub_ps。]

    【讨论】:

      【解决方案3】:

      嗯,我用过:

      __m256 LX = _mm256_load_ps( &X[ i ] );
      __m256 LY = _mm256_load_ps( &Y[ i ] );
      

      代替:

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

      没关系!

      【讨论】:

        猜你喜欢
        • 2018-09-06
        • 1970-01-01
        • 2014-02-02
        • 2017-07-16
        • 1970-01-01
        • 2016-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多