linux - 如何增加新生成进程的 CPU 频率

标签 linux performance fork scheduling

我一直在从事一个爱好项目(用 C 语言编写),但它还远未完成。速度非常重要,因此我最近决定进行一些基准测试,以验证我解决问题的方法是否效率低下。

$ time ./old
real 1m55.92
user 0m54.29
sys 0m33.24

我重新设计了部分程序,以显着删除不必要的操作,减少内存缓存未命中和分支预测错误。出色的 Callgrind 工具向我展示了越来越多令人印象深刻的数字。大多数基准测试都是在没有 fork 外部流程的情况下完成的。

$ 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,以相同的顺序运行相同的程序。

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

#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

我猜不是。

这时候我决定给governor投绩效,日子就变好了:

$ for i in 0 1 2 3 4 5 6 7; do sudo sh -c "echo performance > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor";done
$ time ./test
real 1m03.44
user 0m29.30
sys 0m10.66

似乎每个新进程都被安排在一个单独的核心上,它需要一段时间才能切换到更高的频率。我不能说为什么旧版本跑得更快。也许这是幸运的。也许它(由于效率低下)导致 CPU 更早地选择了更高的频率。

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

我发现改进原始时间的唯一方法是通过在开头添加以下代码将程序(和子进程)限制在单个 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

这不仅是一个 hackish 解决方案,而且在启动的程序使用多线程的情况下也不能很好地工作。我的程序无法知道这一点。

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

最佳答案

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

另外需要注意的是,为了保证公平性,linux调度器在child的第一个epoch共享perent和子进程的执行时间。这可能会对您的问题产生影响。

关于linux - 如何增加新生成进程的 CPU 频率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16761328/

相关文章:

mysql - Grails 2.4.3 & MySQL & grails.project.fork = false

linux - 从文本文件的每一行分配新变量

java.io.IOException : Permission denied but file is created 异常

performance - 理论 VS 实际运行时间评估

java - JNI : Is GetIntArrayElements always linear in time?

C 应用程序在将数据写入管道后挂起。如何检查 "cat"进程是否完成?

linux - Qt Creator 在哪里?

c - 一个 C 程序演示 cmd.exe 和一个 linux shell 例如bash,定界参数?

algorithm - UI 的快速布局算法

c - execvp - 为什么我的程序退出?