我有一个函数定义为
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
类型,英特尔编译器是我唯一的选择。
更多信息:
文件结构非常简单。函数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);
}
我尝试了各种各样的提示,像< code > _ _ attribute _ _((always _ inline))、< code>__forceinline和编译器选项< code>-inline-forceinline,都还没起作用。
完全码
我已经把所有相关的代码以简化的形式放在了一起。如果你有英特尔编译器,你可以试试。使用选项< code>-Winline查看内联报告,使用< code>-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);
}
}
配置
-O3-inline-forceinline-Winline
你知道为什么这个函数不能内联吗?还有到底怎么才能让它内联(我不想求助于宏)?
出于某种原因,英特尔编译器不做卸载代码中函数的内联(我不太熟悉这个概念,所以我不知道这是什么技术原因)。有关详细信息,请参阅有效使用英特尔编译器卸载功能(只需搜索“内联”)。
引用链接文章:
函数内联到卸载构造
有时,为了优化生成代码的性能,内联函数是必要的。在#pragma卸载中直接调用的函数不会被编译器内联,即使它们被标记为内联。为了在卸载区域中实现代码的最佳性能,要么手动内联函数,要么将整个卸载构造放入它自己的函数中。
…
一种解决方案是手动内联函数f,如函数v2所示。
另一个解决方案是将卸载构造移动到它自己的函数中,如函数v3所示。
如果我理解正确,最好的做法是将循环放入一个单独的函数中,该函数也用__attribute((target(mic))标记。
在C++中,我们可以强制函数内联。 这在C#中也是可能的吗?有时,当方法很小时,它会自动内联。但是在C#/.NET中强制内联函数是否可能?
问题内容: 例如,说我的头文件是: 和我的源文件 我可以将源文件拆分为 是否完全出于可读性考虑,而又不担心会对性能产生影响? 问题答案: 您应该标记函数,以便编译器知道它们在该翻译单元中是本地的。 没有编译器就不能假设(除非LTO / WPA)该函数仅被调用一次,因此不太可能内联它。 使用“ LLVM试用”页面进行演示。 就是说,首先要针对可读性的代码进行微优化(这种调整就是微优化),然后再执行性
函数是一个可以重复使用的代码块,CPU 会一条一条地挨着执行其中的代码。CPU 在执行主调函数代码时如果遇到了被调函数,主调函数就会暂停,CPU 转而执行被调函数的代码;被调函数执行完毕后再返回到主调函数,主调函数根据刚才的状态继续往下执行。 一个 C/ C++ 程序的执行过程可以认为是多个函数之间的相互调用过程,它们形成了一个或简单或复杂的调用链条,这个链条的起点是 main(),终点也是 ma
C++ 类 & 对象 C++ 内联函数是通常与类一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。 对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则将会继续使用旧的函数。 如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。如果已定义的函数多
本文向大家介绍C++编程中队内联函数的理解和使用,包括了C++编程中队内联函数的理解和使用的使用技巧和注意事项,需要的朋友参考一下 函数调用过程 c++经过编译生成可执行程序文件exe,存放在外存储器中。程序启动,系统从外存储器中将可执行文件装载到内存中,从入口地址(main函数起始处)开始执行。程序执行中遇到了对其他函数的调用,就暂停当前函数的执行,并保存下一条指令的地址作为从被调函数返回后继续
在我的所有项目中,我都使用gradle并指定以下内容: 现在,我安装了三个不同版本的JDK,从1.6到1.8。为了从一个版本切换到另一个版本,Ishell文件更改、甚至。 偶然的是,我可能会使用错误的JDK版本,而我不希望这样...是否有可能在尝试任何编译任务之前检查编译器版本是否等于targetCompatibility?