我有一个定义为的函数
inline void vec_add(__m512d &v3, const __m512d &v1, const __m512d &v2) {
v3 = _mm512_add_pd(v1, v2);
}
(这__m512d
是在英特尔 MIC 架构上映射到 SIMD 寄存器的本机数据类型)
由于这个函数相当短并且经常被调用,我希望它在每次调用时都被内联。但是英特尔的编译器似乎不愿意内联这个函数,即使在我使用了-inline-forceinline
and-O3
选项之后。它在编译时报告“Forceinline 不接受调用 ...”。由于我必须使用一些编译器特定的功能,例如__m512d
类型,英特尔编译器是我唯一的选择。
更多信息:
文件结构非常简单。该函数vec_add
在一个头文件中定义,该文件mic.h
包含在另一个文件中test.cc
。函数vec_add
只是在循环中重复调用,不涉及函数指针。代码的简化版本test.cc
如下所示
for (int i = 0; i < LENGTH; i += 8) {
// a, b, c are arrays of doubles, and each SIMD register can hold 8 doubles
__mm512d va = _mm512_load_pd(a + i); // load SIMD register from memory
__mm512d vb = _mm512_load_pd(b + i); // ditto
__mm512d vc;
vec_add(vc, va, vb); // store SIMD register to memory
_mm512_store_pd(c + i, vc);
}
我尝试了各种提示,例如__attribute__((always_inline))
,__forceinline
和 compiler option -inline-forceinline
,但都没有奏效。
完整代码
我以简化的形式将所有相关代码放在一起。如果您有英特尔编译器,您可以尝试一下。使用选项-Winline
查看内联报告并-inline-forceinline
强制内联。
#include <stdio.h>
#include <stdlib.h>
#include <immintrin.h>
#define LEN (1<<20)
__attribute((target(mic)))
inline void vec_add(__m512d &v3, const __m512d &v1, const __m512d &v2) {
v3 = _mm512_add_pd(v1, v2);
}
int main() {
#pragma offload target(mic)
{
double *a = (double*)_mm_malloc(LEN*sizeof(double), 64);
double *b = (double*)_mm_malloc(LEN*sizeof(double), 64);
double *c = (double*)_mm_malloc(LEN*sizeof(double), 64);
for (int i = 0; i < LEN; i++) {
a[i] = (double)rand()/RAND_MAX;
b[i] = (double)rand()/RAND_MAX;
}
for (int i = 0; i < LEN; i += 8) {
__m512d va = _mm512_load_pd(a + i);
__m512d vb = _mm512_load_pd(b + i);
__m512d vc;
vec_add(vc, va, vb);
_mm512_store_pd(c + i, vc);
}
_mm_free(a);
_mm_free(b);
_mm_free(c);
}
}
配置
- 编译器:英特尔编译器(ICC)14.0.2
- 编译选项:
-O3 -inline-forceinline -Winline
你知道为什么这个函数不能被内联吗?毕竟我怎样才能让它内联(我不想转向宏)?