当前位置: 首页 > 知识库问答 >
问题:

无法使用Intel编译器强制内联C函数

管和志
2023-03-14

我有一个函数定义为

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);
    }
}

配置

  • 编译器:英特尔编译器(ICC)14.0.2
  • 编译选项:-O3-inline-forceinline-Winline

你知道为什么这个函数不能内联吗?还有到底怎么才能让它内联(我不想求助于宏)?

共有1个答案

桓宜
2023-03-14

出于某种原因,英特尔编译器不做卸载代码中函数的内联(我不太熟悉这个概念,所以我不知道这是什么技术原因)。有关详细信息,请参阅有效使用英特尔编译器卸载功能(只需搜索“内联”)。

引用链接文章:

函数内联到卸载构造

有时,为了优化生成代码的性能,内联函数是必要的。在#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?