c - 帮助编译器优化函数指针

标签 c optimization gcc linux-kernel function-pointers

在 C 中实现类似 OO 的代码封装和多态性的一种常见方法是返回指向包含一些函数指针的结构的不透明指针。例如在 Linux 内核中,这是一种非常常见的模式。

使用函数指针而不是函数调用会引入开销,由于缓存,该开销几乎可以忽略不计,这已在其他问题中讨论过。

但是,随着 GCC (>4.6) 的新 -fwhole-program 和 -flto 优化选项的出现,情况发生了变化。

libPointers.c

#include <stdlib.h>
#include "libPointers.h"

void do_work(struct worker *wrk, const int i) 
{
        wrk->datum += i;
}

struct worker *libPointers_init(const int startDatum)
{
        struct worker *wrk = malloc (sizeof (struct worker));

        *wrk = (struct worker) {
                .do_work = do_work,
                .datum = startDatum
        };

        return wrk;
}

lib指针.h

#ifndef __LIBPOINTERS_H__
#define __LIBPOINTERS_H__


struct worker {
        int datum;

        void (*do_work)(struct worker *, int i);
};

extern void do_work (struct worker *elab, const int i);

struct worker *libPointers_init(const int startDatum);


#endif //__LIBPOINTERS_H__

测试指针.c

#include <stdio.h>
#include "libPointers.h"


int main (void)
{
        unsigned long i;
        struct worker *wrk;

        wrk = libPointers_init(56);

        for (i = 0; i < 1e10; i++) {
#ifdef USE_POINTERS
                wrk->do_work(wrk,i);
#else
                do_work(wrk,i);
#endif
        }

        printf ("%d\n", wrk->datum);
}

使用 -O3 编译,但没有 -flto -fwhole-program 标志,testPointers 在我的机器上执行大约需要 25 秒,无论 USE_POINTERS 是否#defined。

如果我打开 -flto -fwhole-program 标志,使用 USE_POINTERS #defined 的 testPointers 大约需要 25 秒,但如果使用函数调用则大约需要 14 秒。

这是完全预期的行为,因为我知道编译器将内联并优化循环中的函数。然而,我想知道是否有一种方法可以帮助编译器告诉它函数指针是常量,从而也允许它优化这种情况。

对于那些使用 cmake 的人,这是我编译它的方式

CMakeLists.txt

set (CMAKE_C_FLAGS "-O3 -fwhole-program -flto")
#set (CMAKE_C_FLAGS "-O3")
add_executable(testPointers
        libPointers.c
        testPointers.c
        )

最佳答案

编译器无法内联函数,除非它可以确定函数的一个可能版本将被调用。通过指针调用,这种情况并不明显。编译器仍然有可能弄清楚,因为如果您遵循代码,指针可能只有一个可能的值;然而,这超出了我对编译器的期望。

关于c - 帮助编译器优化函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13404007/

相关文章:

python - 更快的 numpy 解决方案而不是 itertools.combinations?

CMAKE/MAKEFILE :/usr/bin/x86_64-linux-gnu-ld : Cannot find -lfftw3f

gcc - 构建包含 LuaJIT 的静态 Linux 二进制文件(使用 musl-libc)时出错

c - 导致程序崩溃的结构

c - C中结构成员的默认值

java - 如何在 Java 中进行混淆器、优化器和混淆器

c++ - 如何确定在给定(游戏)项目上使用定点数的可行性?

c - "the"C 标准是否指定编译器必须遵守哪个标准?

在循环中创建线程

c - 如何在 BST 中添加节点?