首页 > 解决方案 > 程序在 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,其规格如下图所示

在此处输入图像描述


我有一个大发现!替换为 之后arc4randomrandom服务器的性能有了巨大的提升。

标签: cperformanceoptimizationcpuscientific-computing

解决方案


推荐阅读