【发布时间】:2014-05-15 09:13:45
【问题描述】:
我有一个函数定义为
inline void vec_add(__m512d &v3, const __m512d &v1, const __m512d &v2) {
v3 = _mm512_add_pd(v1, v2);
}
(__m512d 是一种本地数据类型映射到英特尔 MIC 架构上的 SIMD 寄存器)
由于这个函数相当短并且经常被调用,我希望在每次调用时都内联它。但英特尔的编译器似乎不愿意内联这个函数,即使我使用了-inline-forceinline 和-O3 选项。它在编译时报告“Forceinline 不接受调用 ...”。因为我必须使用一些编译器特定的功能,例如__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);
}
}
配置
- 编译器:英特尔编译器 (ICC) 14.0.2
- 编译选项:
-O3 -inline-forceinline -Winline
你知道为什么这个函数不能被内联吗? 毕竟我怎样才能让它内联(我不想求助于宏)?
【问题讨论】:
-
你是不是在某处获取函数的地址?
-
你是在同一个模块中调用函数吗?
-
你检查过汇编代码是否真的有跳转到你的函数?
-
@MikeMB 不,我还没有检查程序集。但我尝试将此函数转换为宏,并获得了显着的性能提升。所以我很确定这个函数没有内联。
-
@lei.april 这听起来很合理,不幸的是,这意味着我不知道为什么编译器不想内联函数。但是,由于您已经在函数接口中使用了特定于编译器的类型,我想知道,为什么首先要将对 _mm512_add_pd 的调用放在函数中?