学习使用内在函数——使用 _mm256_sub_ps 的段错误
learning to use intrinsics -- segm fault using _mm256_sub_ps
我正在尝试学习如何使用内部函数。
所以,我的 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 找到最小值 value.Is 我的实现是否正确?
----------------更新----------------
在 Sourav Ghosh 发表评论后,我搜索了 headers。
我找不到 128 位的任何地方,所以我使用 #include <immintrin.h>
使用 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
没关系。
BUt 运行 代码给出了分段错误..
行内:
Xd = _m256_sub_ps( theX[ i ] , xIdx );
Yd = _m256_sub_ps( theY[ i ] , yIdx );
我认为,您缺少一些包含 _m128_sub_ps()
函数前向声明的必需头文件。我们可以假设实际上 _m128_sub_ps()
函数具有 return 类型的 __m128
,但是如果没有适当的前向声明,编译器会假设 default return 为 _m128_sub_ps()
函数键入 int
。这就是为什么编译器发出
function "_m128_sub_ps" declared implicitly
然后,int
return 值被分配给类型为 __m128
的变量,造成了问题。
编辑:
根据更改后的代码,
int x , y; // pixel coordinates
应该是
__m256 x , y; // pixel coordinates
因为 signature of _mm256_sub_ps()
要求两个参数都是 __m256
类型
您对内在名称有点困惑。
对于 128 位 SSE,它只是,例如:
_mm_sub_ps
不是:
_mm128_sub_ps
[混淆可能是因为 256 位 AVX 是 _mm256_sub_ps
。]
嗯,我用过:
__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 );
没关系!
我正在尝试学习如何使用内部函数。 所以,我的 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 找到最小值 value.Is 我的实现是否正确?
----------------更新----------------
在 Sourav Ghosh 发表评论后,我搜索了 headers。
我找不到 128 位的任何地方,所以我使用 #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
没关系。
BUt 运行 代码给出了分段错误..
行内:
Xd = _m256_sub_ps( theX[ i ] , xIdx );
Yd = _m256_sub_ps( theY[ i ] , yIdx );
我认为,您缺少一些包含 _m128_sub_ps()
函数前向声明的必需头文件。我们可以假设实际上 _m128_sub_ps()
函数具有 return 类型的 __m128
,但是如果没有适当的前向声明,编译器会假设 default return 为 _m128_sub_ps()
函数键入 int
。这就是为什么编译器发出
function "_m128_sub_ps" declared implicitly
然后,int
return 值被分配给类型为 __m128
的变量,造成了问题。
编辑:
根据更改后的代码,
int x , y; // pixel coordinates
应该是
__m256 x , y; // pixel coordinates
因为 signature of _mm256_sub_ps()
要求两个参数都是 __m256
您对内在名称有点困惑。
对于 128 位 SSE,它只是,例如:
_mm_sub_ps
不是:
_mm128_sub_ps
[混淆可能是因为 256 位 AVX 是 _mm256_sub_ps
。]
嗯,我用过:
__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 );
没关系!