我在MIC(intel Xeon Phi协处理器)上进行手动矢量化,我在做一个简单的计算基准(实际上是对CPU和MIC进行基准测试,并分析矢量化效果auto和manual)。我想试试内在的效果。这里是我在CPU上的问题,我可以观察到m256内部函数的性能提高了30%(与没有内部函数的CPU相比),但是在m512的MIC上,性能与没有内部函数的MIC(OpenMP+内部函数)相同,这正常吗?
MIC+INTR~3.18秒
麦克风~3.19秒
CPU+INTR~4.31秒
CPU~6.47秒
我使用的选项:(英特尔编译器)
要编译为MIC+内在的:-O3-openmp-DWITH_INTR-restrict
编译MIC:-O3-openmp-restrict
为CPU+内部编译:-O3-openmp-DWITH_INTR-no offload-restrict
为CPU编译:-O3-openmp-no offload-restrict
我的硬件配置:
CPU:Intel(R)Xeon(R)CPU E5-2680 [email protected] | SandyBridge(2x8核| 32线程)
MIC:Intel(R)Xeon Phi(TM)协处理器x100系列(61核244线程)
代码看起来很长,但这仅仅是因为没有使用内部函数的计算,以及使用256位向量和512位向量的计算。
以及要为其复制结果的代码:
#include <stdio.h>
#include <omp.h>
#include <offload.h>
#include <math.h>
#include <immintrin.h>
#define N 2<<17
#define P 2<<14
__declspec(target(mic:0)) void testVctr( double * restrict a, double * restrict b, double * restrict c )
{
double t1( omp_get_wtime() );
omp_set_num_threads(omp_get_max_threads());
__assume_aligned( a, 64 );
__assume_aligned( b, 64 );
__assume_aligned( c, 64 );
int i;
int j;
int k;
#ifdef WITH_INTR
#ifdef __MIC__
__m512d n1 = _mm512_set1_pd( 1. );
__m512d n1024 = _mm512_set1_pd( 1024. );
__m512d n230 = _mm512_set1_pd( 230. );
#else
__m256d n1 = _mm256_set1_pd( 1. );
__m256d n1024 = _mm256_set1_pd( 1024. );
__m256d n230 = _mm256_set1_pd( 230. );
#endif
#endif
#pragma omp parallel for private( i, j, k ) schedule( dynamic )
for( i=0; i<N; ++i )
{
#ifdef WITH_INTR
#ifdef __MIC__
double * restrict A = (double *restrict) _mm_malloc( (size_t)( (8) * sizeof(double) ), 64 );
__m512d res = _mm512_setzero_pd(), r0, r1;
for( j=0; j<P; j+=8 )
{
r0 = _mm512_load_pd( &b[j] );
r0 = _mm512_add_pd( r0, n1 );
r0 = _mm512_div_pd( n1, r0 );
r0 = _mm512_exp_pd( r0 );
r1 = _mm512_load_pd( &c[j] );
r1 = _mm512_mul_pd( r1, n1024 );
r1 = _mm512_add_pd( r1, n230 );
r1 = _mm512_log_pd( r1 );
r0 = _mm512_div_pd( r0, r1 );
res = _mm512_add_pd( res, r0 );
}
_mm512_store_pd( A, res );
double tmp(0.);
for( k=0; k<8; ++k )
tmp += A[k];
a[i] = tmp;
_mm_free( (double * restrict) A );
#else
double * restrict A = (double * restrict) _mm_malloc( (size_t)( (4) * sizeof(double) ), 64 );
__m256d res = _mm256_setzero_pd(), r0, r1;
for( j=0; j<P; j+=4 )
{
r0 = _mm256_load_pd( &b[j] );
r0 = _mm256_add_pd( r0, n1 );
r0 = _mm256_div_pd( n1, r0 );
r0 = _mm256_exp_pd( r0 );
r1 = _mm256_load_pd( &c[j] );
r1 = _mm256_mul_pd( r1, n1024 );
r1 = _mm256_add_pd( r1, n230 );
r1 = _mm256_log_pd( r1 );
r0 = _mm256_div_pd( r0, r1 );
res = _mm256_add_pd( res, r0 );
}
_mm256_store_pd( A, res );
double tmp(0.);
for( k=0; k<4; ++k )
tmp += A[k];
a[i] = tmp;
_mm_free( (double * restrict) A );
#endif
#else
double res = 0.;
#pragma simd
for( j=0; j<P; ++j )
{
double tmp0 = 1./(b[j]+1.);
double tmp1 = exp( tmp0 );
double tmp2 = c[j] * 1024;
double tmp3 = tmp2 + 230;
double tmp4 = log( tmp3 );
double tmp5 = tmp1 / tmp4;
res += tmp5;
}
a[i] = res;
#endif
}
printf("\nElapsed time: %f sec\n", omp_get_wtime() - t1 );
}
int main( void )
{
int i;
printf("\nOuter loop (N) %d iterations \nInner loop (P) %d iterations\n", N, P );
double * restrict a = (double * restrict) _mm_malloc( (size_t)( (N) * sizeof(double) ), 64 );
double * restrict b = (double * restrict) _mm_malloc( (size_t)( (P) * sizeof(double) ), 64 );
double * restrict c = (double * restrict) _mm_malloc( (size_t)( (P) * sizeof(double) ), 64 );
for( i=0; i<P; ++i )
{
b[i] = rand()/RAND_MAX;
c[i] = rand()/RAND_MAX;
}
#pragma offload target( mic : 0 ) \
out( a : length( N ) align(512) ) \
in ( b : length( P ) align(512) ) \
in ( c : length( P ) align(512) )
testVctr( a, b, c );
printf( "\nCheck last result: %f (~ 1.)\n", a[N-1]*2./(P) );
_mm_free( (double * restrict) a );
_mm_free( (double * restrict) b );
_mm_free( (double * restrict) c );
return 0;
}
也许,我遗漏了代码中的某些内容或编译命令中的某些选项。
我会尝试任何建议。
谢谢您。
GS公司
最佳答案
在循环的每一次迭代中,你最大的一个慢下来的地方就是你在“malloc ing”然后“free”了。堆分配非常缓慢。你最好做一个简单的堆栈分配,即。
__declspec( align( 64 ) ) double A[8];
当动态堆管理被完全删除时,这可能会显著提高性能。
也就是说这不是你的主要问题。英特尔编译器很可能很好地对循环进行了矢量化。您应该看看编译器和内部函数生成的程序集,看看其中一个是否比另一个好。如果intrinsics程序集看起来更好,那么很可能您看到的大部分时间都被内存访问占用了。。。
关于c - 性能AVX-512与MIC上的自动矢量化(英特尔至强融核协处理器),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27945345/