- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用下面的C程序(与gcc一起编译)来测量给定代码段的计算时间。
问题在于,当在之外的之外使用函数时,正在分析的代码段会在uleep()
中获得不同的度量。
#include <unistd.h>
#include <stdio.h>
#include <time.h>
int main()
{
int f = 0;
while (f < 10)
{
double sum = 1.0;
struct timespec t0, t1;
clock_gettime(CLOCK_MONOTONIC, &t0);
// CODE SECTION BEING PROFILED
for (unsigned int i = 0; i < 5e6; i++)
sum += 0.001;
// END OF CODE SECTION BEING PROFILED
clock_gettime(CLOCK_MONOTONIC, &t1);
double elapsed_time = t1.tv_sec - t0.tv_sec;
elapsed_time += (t1.tv_nsec - t0.tv_nsec) * 1e-9;
printf("%.2f ms\n", elapsed_time*1000 );
f++;
// Sleep causing fake clock_gettime measurements?
usleep(50000);
}
return 0;
}
下面,当对elapsed_time
进行注释时,我粘贴程序的结果:uleep(50000)
时的结果:uleep(50000)
中的不同时钟来测量时间,也尝试使用C++ clock_gettime()
来测量时间。但是,在所有情况下结果都是相似的。std::chrono::high_resolution_clock
。在这种情况下,尽管获得的时间要短得多,但是当存在O2
时,与不存在usleep()
时相比,仍有一些测量值比〜3x 高。usleep()
中使用的微秒数会影响最终的测量时间,例如用10000us我得到:usleep()
引起了相同的问题(请参见下面的代码)。#include <unistd.h>
#include <stdio.h>
#include <time.h>
int main()
{
double total_time = 0.0;
int f = 0;
while (f < 1000)
{
double sum = 1.0;
struct timespec t0, t1;
clock_gettime(CLOCK_MONOTONIC, &t0);
// Code section being profiled
for (unsigned int i = 0; i < 5e6; i++)
sum += 0.001;
// End of Code section being profiled
clock_gettime(CLOCK_MONOTONIC, &t1);
double elapsed_time = t1.tv_sec - t0.tv_sec;
elapsed_time += (t1.tv_nsec - t0.tv_nsec) * 1e-9;
total_time += elapsed_time;
f++;
// Sleep/printf causing fake clock_gettime measurements?
printf("%.2f ms\n", elapsed_time*1000 );
// usleep(10000);
}
printf("TOTAL TIME: %.2f ms\n", total_time*1000 );
return 0;
}
结果printf()
f编译的代码时,总时间为:g++ -g
行时的(注意,该行再次位于要分析的部分的外部)。 printf("%.2f ms\n", elapsed_time*1000 );
)编译的,则我获得的总时间为:g++ -O2
)。 printf()
不存在时)。 printf()
相比,使用printf()
时,测量的时间增加的程度较小。因此,usleep()
似乎不是导致此问题的唯一函数...usleep()
,CLOCK_MONOTONIC_RAW
和CLOCK_PROCESS_CPUTIME_ID
。它们都提供相同的行为。CLOCK_REALTIME
的返回值以丢弃失败。
最佳答案
您好像是CPU frequency scaling的受害者。
CPU频率缩放
您的CPU缩放驱动程序会根据各种因素来调节CPU频率,但重要的是根据当前的CPU负载来调节CPU频率。 Linux内核有各种可用的驱动程序,以及不同的缩放调节器。每个驱动程序都可以支持一组定标的调速器,并且根据当前 Activity 的调速器而表现不同。
例如,笔记本电脑上的默认驱动程序是intel_pstate
,以及可用的调控器powersave
和performance
。如果将驱动程序更改为acpi-cpufreq
,我还将获得ondemand
,userspace
和conservative
。
不同调速器之间的主要区别在于它们的名称:powersave
调速器将尝试使CPU保持较低的频率以节省功率,而performance
调速器将尝试使CPU保持较高的频率以使运行更快。
在某些情况下,performance
调控器仅将CPU频率固定为最大可用频率(对我来说,这就是intel_pstate
驱动程序发生的情况)。在其他情况下,它只会尝试使其保持“高电平”,但仍会进行调整(对我来说,这就是acpi-cpufreq
驱动程序发生的情况)。
无论如何,缩放驱动程序和调节器的组合可动态调节CPU频率,将考虑CPU负载,以便在可能的情况下即时进行频率调整。这可能在通过系统调用输入内核代码时发生,也可能在内核本身运行调度程序以重新调度当前正在运行的进程时在调度记号上发生。
怎么了?
您很可能结合使用缩放驱动程序和调节器来动态设置CPU频率。
当您的代码在不调用usleep()
的情况下运行时,CPU负担很重,并且频率基本稳定。但是,如果您的代码调用usleep()
,则将大大减少CPU负载,并且缩放驱动程序会降低CPU频率。到睡眠后内核将进程唤醒时,频率要低得多,并且在缩放驱动器意识到需要增强之前需要花费一些时间。如果您保持规律的睡眠时间,则驱动程序将永远没有足够的时间来重新调整频率备份,并且代码将运行得更慢。
这也适用于printf()
,它需要进行write()
syscall才能打印文本,并且几乎适用于所有其他syscall。在用户空间和内核空间之间切换会减慢该过程,从而使频率被缩放驱动器降低。对于某些系统调用(如clock_gettime()
),不会发生这种情况,该调用已优化为在用户空间中运行,并且不需要上下文切换。
这是我的计算机上带有动态调节器(例如ondemand
)的示例:
您可以清楚地看到,CPU频率在第一次运行时(没有usleep()
)卡在最大值,然后上下波动而没有足够的时间在第二次运行时稳定(使用usleep()
)。您实际上可以注意到,测试2的avg
时间几乎是测试1的3倍。我的机器上的acpi-cpufreq
和Governor performance
也会发生这种情况。
解
如果您能够设置不同的缩放驱动程序/总督组合,以保持固定的CPU频率,则两个版本的代码在时序上不会有差异。
这是我的计算机上的另一个示例,其CPU频率为静态(例如,使用userspace
调节器并手动设置固定速度):
如您所见,这两个测试大约在同一时间运行。
如果您无法设置其他缩放比例调节器,请尝试更改内核的缩放比例驱动程序。如果运行Debian或Ubuntu,则可能具有用于不同扩展驱动程序的可加载模块。
通过查看当前的内核配置,可以查看内核的可用缩放驱动程序和调控器:
cat /boot/config-$(uname -r) | grep FREQ
...
CONFIG_X86_PCC_CPUFREQ=m
CONFIG_X86_ACPI_CPUFREQ=m
...
m
表示“作为模块可用”(可通过
modprobe
加载),而
y
表示“内置”。
# Load acpi-cpufreq since we have CONFIG_X86_ACPI_CPUFREQ=m
sudo modprobe acpi_cpufreq
# Switch driver
echo acpi-cpufreq | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_driver
# Check available governors for the driver
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_available_governors
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <sched.h>
#include <sys/types.h>
/**
* Marco Bonelli - 2020-03-02
* https://stackoverflow.com/a/60481392/3889449
*
* Test the effect of different scaling governors on CPU frequency and
* performance under:
*
* 1) Continuous heavy load.
* 2) Intermittent and short heavy load.
*
* gcc -O3 scaling_governor_test.c -o test
* ./test [N_RUNS] [N_CYCLES_PER_RUN] [TEST2_DELAY_US]
*/
#define DEFAULT_RUNS 1000
#define DEFAULT_CYCLES 1000 * 1000
#define DEFAULT_DELAY 100 * 1000
// Don't optimize this as GCC would basically trash the whole function.
#pragma GCC push_options
#pragma GCC optimize("O0")
void __attribute__ ((noinline)) func(unsigned n) {
double sum = 1.0;
for (unsigned i = 0; i < n; i++)
sum += 0.001;
}
#pragma GCC pop_options
void warmup(unsigned runs, unsigned cycles) {
for (unsigned n = 1; n <= runs; n++)
func(cycles);
}
double bench(unsigned n) {
struct timespec t0, t1;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t0);
func(n);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
return (t1.tv_sec - t0.tv_sec)*1000.0L + (t1.tv_nsec - t0.tv_nsec)/1000.0L/1000.0L;
}
void setup_affinity(void) {
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(0, &set);
if (geteuid() == 0) {
if (sched_setaffinity(0, sizeof(set), &set) == 0)
puts("Affinity set to CPU #0.");
else
perror("sched_setaffinity");
} else {
puts("Running as normal user, run as root to set CPU affinity.");
}
}
int main(int argc, char **argv) {
unsigned runs, cycles, delay;
double cur, tot1, tot2, min, max, avg;
if (argc < 2 || sscanf(argv[1], "%i", &runs) != 1 || runs < 1)
runs = DEFAULT_RUNS;
if (argc < 3 || sscanf(argv[2], "%i", &cycles) != 1 || cycles < 1)
cycles = DEFAULT_CYCLES;
if (argc < 4 || sscanf(argv[3], "%i", &delay) != 1 || delay < 1)
delay = DEFAULT_DELAY;
setup_affinity();
printf("Benchmarking %u runs of %u cycles each.\n", runs, cycles);
printf("Test #1 will proceed normally.\nTest #2 will usleep(%u) before each run.\n", delay);
fputs("Warming up... ", stdout);
fflush(stdout);
warmup(10, cycles);
puts("done.\n---");
tot1 = 0;
min = INFINITY;
max = -INFINITY;
for (unsigned n = 1; n <= runs; n++) {
cur = bench(cycles);
tot1 += cur;
avg = tot1 / n;
if (cur < min) min = cur;
if (cur > max) max = cur;
printf("\rTest #1: tot %-9.3f avg %-7.3f min %-7.3f max %-7.3f [ms]", tot1, avg, min, max);
fflush(stdout);
}
putchar('\n');
tot2 = 0;
min = INFINITY;
max = -INFINITY;
for (unsigned n = 1; n <= runs; n++) {
usleep(delay);
cur = bench(cycles);
tot2 += cur;
avg = tot2 / n;
if (cur < min) min = cur;
if (cur > max) max = cur;
printf("\rTest #2: tot %-9.3f avg %-7.3f min %-7.3f max %-7.3f [ms]", tot2, avg, min, max);
fflush(stdout);
}
puts("\n---");
if (tot1 < tot2)
printf("Test #2 ran ~%.3fx slower than Test #1.\n", tot2/tot1);
else if (tot1 > tot2)
printf("Test #1 ran ~%.3fx slower than Test #2.\n", tot1/tot2);
else
puts("Reality is a simulation.");
if (avg < 0.5)
puts("Such low average times are not a good indicator. You should re-run the rest with different parameters.");
return 0;
}
关于c++ - 由于配置文件部分之外的代码,使用clock_gettime()进行不合理的时间测量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60351509/
我喜欢 smartcase,也喜欢 * 和 # 搜索命令。但我更希望 * 和 # 搜索命令区分大小写,而/和 ?搜索命令遵循 smartcase 启发式。 是否有隐藏在某个地方我还没有找到的设置?我宁
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 10年前关闭。 Improve this qu
从以下网站,我找到了执行java AD身份验证的代码。 http://java2db.com/jndi-ldap-programming/solution-to-sslhandshakeexcepti
似乎 melt 会使用 id 列和堆叠的测量变量 reshape 您的数据框,然后通过转换让您执行聚合。 ddply,从 plyr 包看起来非常相似..你给它一个数据框,几个用于分组的列变量和一个聚合
我的问题是关于 memcached。 Facebook 使用 memcached 作为其结构化数据的缓存,以减少用户的延迟。他们在 Linux 上使用 UDP 优化了 memcached 的性能。 h
在 Camel route ,我正在使用 exec 组件通过 grep 进行 curl ,但使用 ${HOSTNAME} 的 grep 无法正常工作,下面是我的 Camel 路线。请在这方面寻求帮助。
我正在尝试执行相当复杂的查询,在其中我可以排除与特定条件集匹配的项目。这是一个 super 简化的模型来解释我的困境: class Thing(models.Model) user = mod
我正在尝试执行相当复杂的查询,我可以在其中排除符合特定条件集的项目。这里有一个 super 简化的模型来解释我的困境: class Thing(models.Model) user = mod
我发现了很多嵌入/内容项目的旧方法,并且我遵循了在这里找到的最新方法(我假设):https://blog.angular-university.io/angular-ng-content/ 我正在尝试
我正在寻找如何使用 fastify-nextjs 启动 fastify-cli 的建议 我曾尝试将代码简单地添加到建议的位置,但它不起作用。 'use strict' const path = req
我正在尝试将振幅 js 与 React 和 Gatsby 集成。做 gatsby developer 时一切看起来都不错,因为它发生在浏览器中,但是当我尝试 gatsby build 时,我收到以下错
我试图避免过度执行空值检查,但同时我想在需要使代码健壮的时候进行空值检查。但有时我觉得它开始变得如此防御,因为我没有实现 API。然后我避免了一些空检查,但是当我开始单元测试时,它开始总是等待运行时异
尝试进行包含一些 NOT 的 Kibana 搜索,但获得包含 NOT 的结果,因此猜测我的语法不正确: "chocolate" AND "milk" AND NOT "cow" AND NOT "tr
我正在使用开源代码共享包在 iOS 中进行 facebook 集成,但收到错误“FT_Load_Glyph failed: glyph 65535: error 6”。我在另一台 mac 机器上尝试了
我正在尝试估计一个标准的 tobit 模型,该模型被审查为零。 变量是 因变量 : 幸福 自变量 : 城市(芝加哥,纽约), 性别(男,女), 就业(0=失业,1=就业), 工作类型(失业,蓝色,白色
我有一个像这样的项目布局 样本/ 一种/ 源/ 主要的/ java / java 资源/ .jpg 乙/ 源/ 主要的/ java / B.java 资源/ B.jpg 构建.gradle 设置.gr
如何循环遍历数组中的多个属性以及如何使用map函数将数组中的多个属性显示到网页 import React, { Component } from 'react'; import './App.css'
我有一个 JavaScript 函数,它进行 AJAX 调用以返回一些数据,该调用是在选择列表更改事件上触发的。 我尝试了多种方法来在等待时显示加载程序,因为它当前暂停了选择列表,从客户的 Angul
可能以前问过,但找不到。 我正在用以下形式写很多语句: if (bar.getFoo() != null) { this.foo = bar.getFoo(); } 我想到了三元运算符,但我认
我有一个表单,在将其发送到 PHP 之前我正在执行一些验证 JavaScript,验证后的 JavaScript 函数会发布用户在 中输入的文本。页面底部的标签;然而,此消息显示短暂,然后消失...
我是一名优秀的程序员,十分优秀!