c - 程序在 2.5GHz Xeon 上运行比 2.3GHz Core i5 慢 10 倍
问题描述
我正在使用以下代码进行一些蒙特卡罗模拟。
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#define L 20
#define N 200000
int main() {
struct timespec ts_start, ts_end;
clock_t clk_start, clk_end;
struct rusage usage;
struct timeval tv_ustart, tv_uend;
struct timeval tv_sstart, tv_send;
clock_gettime(CLOCK_MONOTONIC, &ts_start);
clk_start = clock();
getrusage(RUSAGE_SELF, &usage);
tv_ustart = usage.ru_utime;
tv_sstart = usage.ru_stime;
/*
* the runtime of one simulation may vary a lot, so let's repeat it many times.
*/
for (int iteration = 0; iteration < N; iteration += 1) {
int node_num_by_depth[L + 1] = {1};
for (int level = 0; level < L; level += 1) {
for (int depth = level; depth != -1; depth -= 1) {
int parent_num = node_num_by_depth[depth];
node_num_by_depth[depth] = 0;
for (int parent = 0; parent < parent_num; parent += 1) {
int child_num = 1 + arc4random() % 2;
int child_depth = depth + (child_num > 1);
node_num_by_depth[child_depth] += child_num;
}
}
}
}
clock_gettime(CLOCK_MONOTONIC, &ts_end);
clk_end = clock();
getrusage(RUSAGE_SELF, &usage);
tv_uend = usage.ru_utime;
tv_send = usage.ru_utime;
double elapsed = (double) (ts_end.tv_sec - ts_start.tv_sec)
+ (double) (ts_end.tv_nsec - ts_start.tv_nsec) / 1E9;
printf("Wall clock time elapsed: %g\n", elapsed);
double cpu_time_used = ((double) (clk_end - clk_start)) / CLOCKS_PER_SEC;
printf("CPU time elapsed: %g\n", cpu_time_used);
printf("User CPU time elapsed: %lu.%06u\n",
tv_uend.tv_sec - tv_ustart.tv_sec,
tv_uend.tv_usec - tv_ustart.tv_usec);
printf("System CPU time elapsed: %lu.%06u\n",
tv_send.tv_sec - tv_sstart.tv_sec,
tv_send.tv_usec - tv_sstart.tv_usec);
}
在我的MacBook Pro上运行时2.3GHz dual-core Intel Core i5, Turbo Boost up to 3.6GHz, with 64MB of eDRAM
,输出为
Wall clock time elapsed: 32.408
CPU time elapsed: 32.3566
User CPU time elapsed: 32.319151
System CPU time elapsed: 32.319114
在我的 FreeBSD 服务器上运行时CPU: Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz (2499.96-MHz K8-class CPU)
,它给了我
Wall clock time elapsed: 396.563
CPU time elapsed: 396.414
User CPU time elapsed: 158.377633
System CPU time elapsed: 158.376629
在这两种情况下,我使用的编译指令都是clang main.c -Ofast -march=native -o main
.
最初,服务器运行的是 Ubuntu 18.04,但在意识到我的程序运行速度非常慢后,我切换到了 FreeBSD。然而,即使在 FreeBSD(arc4random
本地提供)上,它的效率仍然显着降低。现在,除非有很好的理由,否则我不想再次切换到新的操作系统。
我已使用 对程序进行了概要分析gprof
,您可以在此处找到结果。我们可以看到arc4random
花费了相当多的时间(30.8%),但这并不是导致十倍性能损失的唯一原因。
正如评论所指出的,我添加了一些其他的时间度量。您可以看到挂钟时间和 CPU 时间之间存在巨大差距。我可以缩小它吗?无论如何,我关心的是执行我的程序需要多长时间,而不是需要多少 CPU 周期。
这是有关我的 MacBook Pro 的一些扩展信息
Hardware Overview:
Model Name: MacBook Pro
Model Identifier: MacBookPro14,1
Processor Name: Intel Core i5
Processor Speed: 2.3 GHz
Number of Processors: 1
Total Number of Cores: 2
L2 Cache (per Core): 256 KB
L3 Cache: 4 MB
Memory: 8 GB
Boot ROM Version: 184.0.0.0.0
SMC Version (system): 2.43f6
Serial Number (system): XXXXXXXXXXXX
Hardware UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
我的服务器配备了 12 个Intel Skylake Xeon Platinum 8163 2.5GHz CPU,其规格如下图所示
我有一个大发现!替换为 之后arc4random
,random
服务器的性能有了巨大的提升。
MacBook Pro 与
random
Wall clock time elapsed: 5.61316 CPU time elapsed: 5.40623 User CPU time elapsed: 5.361931 System CPU time elapsed: 5.359096
服务器与
random
Wall clock time elapsed: 6.69183 CPU time elapsed: 6.6875 User CPU time elapsed: 6.690042 System CPU time elapsed: 6.689085
解决方案
推荐阅读
- go - 如何在 GORM 中使用从 BOM 到 Part 的两个外键来实现特定的 Part/BOM 设计?
- excel - 根据单元格值绘制形状
- python - Pool 只执行一个线程而不是 4 个,如何让它无限?
- c - 试图在输入(字符数组)中间返回字符会给出“分段错误(核心转储)”?
- reactjs - React:如何在其类之外访问 props 对象?
- bash - 如何在 Bash 中更新多个 git 存储库的远程 url?
- c# - 在 C# 中从 SQLite 查询日期时间
- python - 用 Python 转录音频文件
- c++ - 多个凸形角连接
- kubernetes - GCloud kubernetes cluster with 1 Insufficient cpu error