Linux 如何提高新生成进程的CPU频率

Linux 如何提高新生成进程的CPU频率,linux,performance,fork,scheduling,Linux,Performance,Fork,Scheduling,我从事一个爱好项目已有一段时间了(用C语言编写),但它还远未完成。它的速度非常重要,所以我最近决定做一些基准测试,以验证我解决问题的方法不会低效 $ time ./old real 1m55.92 user 0m54.29 sys 0m33.24 我重新设计了程序的各个部分,以显著消除不必要的操作,减少内存缓存未命中和分支预测失误。奇妙的Callgrind工具向我展示了越来越多令人印象深刻的数字。大多数基准测试都是在没有分叉外部流程的情况下完成的 $ time ./old --dry-run

我从事一个爱好项目已有一段时间了(用C语言编写),但它还远未完成。它的速度非常重要,所以我最近决定做一些基准测试,以验证我解决问题的方法不会低效

$ time ./old
real 1m55.92
user 0m54.29
sys 0m33.24
我重新设计了程序的各个部分,以显著消除不必要的操作,减少内存缓存未命中和分支预测失误。奇妙的Callgrind工具向我展示了越来越多令人印象深刻的数字。大多数基准测试都是在没有分叉外部流程的情况下完成的

$ time ./old --dry-run
real 0m00.75
user 0m00.28
sys 0m00.24

$ time ./new --dry-run
real 0m00.15
user 0m00.12
sys 0m00.02
显然,我至少做了一些正确的事情。然而,真正运行这个程序却说明了一个不同的故事

$ time ./new
real 2m00.29
user 0m53.74
sys 0m36.22
正如您可能已经注意到的,时间主要取决于外部过程。我不知道是什么导致了衰退。这没什么奇怪的;只是一个传统的vfork/execve/waitpid,由一个线程完成,以相同的顺序运行相同的程序

一定是什么原因导致了分叉速度变慢,所以我做了一个小测试(类似于下面的测试),它只会产生新的进程,并且没有与我的程序相关的开销。显然,这必须是最快的

#define _GNU_SOURCE
#include <fcntl.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, const char **argv)
{
    static const char *const _argv[] = {"/usr/bin/md5sum", "test.c", 0};

    int fd = open("/dev/null", O_WRONLY);
    dup2(fd, STDOUT_FILENO);
    close(fd);

    for (int i = 0; i < 100000; i++)
    {
        int pid = vfork();
        int status;
        if (!pid)
        {
            execve("/usr/bin/md5sum", (char*const*)_argv, environ);
            _exit(1);
        }
        waitpid(pid, &status, 0);
    }
    return 0;
}

$ time ./test
real 1m58.63
user 0m68.05
sys 0m30.96
似乎每一个新进程都安排在一个单独的核心上,需要一段时间才能切换到更高的频率。我说不出为什么旧版本运行得更快。也许这是幸运的。可能是(由于效率低下)导致CPU更早地选择了更高的频率

更改调控器的一个很好的副作用是编译时间也得到了改进。显然,编译需要很多新的过程。但这不是一个可行的解决方案,因为该程序必须在其他人的台式机(和笔记本电脑)上运行

我发现改进原始时间的唯一方法是在开始时添加以下代码,将程序(和子进程)限制为单个CPU:

cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
sched_setaffinity(0, sizeof(mask), &mask);
尽管使用了默认的“ondemand”调控器,但哪种调控器实际上是最快的:

$ time ./test
real 0m59.74
user 0m29.02
sys 0m10.67
它不仅是一个黑客的解决方案,而且在启动的程序使用多个线程的情况下也不能很好地工作。我的程序不可能知道这一点

有人知道如何让派生的进程以高CPU时钟频率运行吗?它必须是自动化的,不需要su特权。虽然到目前为止我只在Linux上测试过,但我打算将其移植到几乎所有流行和不受欢迎的桌面操作系统上(它也将在服务器上运行)。任何平台上的任何想法都是受欢迎的。

CPU频率被(大多数OSs)视为系统属性。因此,没有根权限,您无法更改它。存在一些关于扩展的研究,以允许采用特定的程序;但是,由于即使对于相同的通用体系结构,能量/性能模型也有所不同,因此您很难找到通用的解决方案


此外,请注意,为了保证公平性,linux调度程序在子进程的第一个历元中共享perent和子进程的执行时间。这可能会对你的问题产生影响。

几乎肯定还有其他事情发生在这里,你没有考虑。在任何真正的计算机上,活动的CPU调控器在性能上不会造成如此程度的差异。你的计划是什么?它在做什么,它是如何做的,你是如何测试它的?请尝试测试代码。对我来说,它运行在1M14秒与ondemand总督和32秒与性能(在核心i7-2600)。我和你一样惊讶。我指的是
/new
中显示的性能差异。我的程序非常类似于shell脚本解释器。(尽管强调脚本)。我最初尝试将命令放在bash脚本中,它显示了相同的性能特征。现在看来shell脚本运行效率很低。
$ time ./test
real 0m59.74
user 0m29.02
sys 0m10.67