我有一个函数定义如下:
inline void vec_add(__m512d &v3, const __m512d &v1, const __m512d &v2) {
v3 = _mm512_add_pd(v1, v2);
}
(__m512d
是一种本地数据类型,映射到Intel MIC体系结构上的SIMD寄存器)
由于这个函数非常短且频繁调用,我希望在每次调用时都能将其内联。但是,即使我使用了-inline-forceinline
和-O3
选项,Intel的编译器似乎仍不愿意将该函数内联。在编译时,它报告“Forceinline not honored for call ...”。由于我必须使用一些编译器特定功能,例如__m512d
类型,因此Intel编译器是我的唯一选择。
更多信息:
文件结构非常简单。函数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
和编译器选项-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);
}
}
配置
- 编译器: Intel编译器(ICC) 14.0.2
- 编译选项:
-O3 -inline-forceinline -Winline
您有什么想法,为什么这个函数无法内联呢? 而我怎样才能在最终将其内联(我不想使用宏)?