さて、過去にVisual Studio × C言語のベンチマークテストをしました。まだ読んでないよ~という方は以下のリンクからぜひチェックしてみてください。

→【連載】自作コードでC言語のベンチマーク計測#1 ~ Visual Studioで計測!不明点は生成AIに聞いてみよう ~

不思議に思った方もいるのではないでしょうか?ゲーミングPCやクリエイター向けPCが1人1台所有となりつつあるこのご時世。(なんなら、パソコンは1人1台の時代は疾うの昔に過ぎ去り、スマートフォンの性能が一昔前のPCスペックを超える時代)巷ではベンチマーク計測なんて、「Cine◯ench」やら「3◯Mark」やら、「なんちゃらファンタジーやなんちゃらクエスト、なんちゃらハンターを快適に遊ぶための計測アプリ」が公式から出ています。なんでC言語でベンチマーク測るの?とイマドキこんな手法をしていることに疑問を抱いた方も少なからずいると思います。

お気づきの方もいるかも知れませんが、これらのアプリケーションは基本「高性能であることを前提」としていたり、「プラットフォームに依存」していたりします。我々のような組込み機器やそれらに関連する開発をしてるエンジニアが使うようなPCではなく、もっとゲームなどの重い画像処理を行うようなPC向けのもののようです。

ということで、組込みLinux環境や、古くてWindowsだと遅くてイライラするから、OSをUbuntuに書き換えて使用するような、へなちょこPCでもベンチマークを計測して性能の違いを調べたい!という欲望から(今話題の生成AIを使って)私が作ったソースコードになります。これがC言語でわざわざ性能調査をし始めた理由です。

 

今回確認した環境

前置きが少し長くなりましたが、いよいよ本題です。
今回は以下のマシンを使用しています。

  • Ubuntu 22.04
    • WindowsOSだと重くて使い物にならなくなった7年モノのPCにシングルブートで構築
      • プロセッサ:intel core i7-6500U
      • 実装 RAM:16 GB
      • ストレージ:500 GB HDD
      • システム:64 bit
    • 普段使用している5年モノのWindowsPC上に構築した仮想OS(VirtualBox)
      ホストPC
      • プロセッサ:AMD Ryzen 7 4700U with Radeon Graphics 2.00 GHz
      • 実装 RAM:16.0 GB
      • ストレージ:477 GB SSD
      • システム:64 bit
  • Milk-V Duo256M
    • 小さなコンピュータ基板(SBC:シングルボードコンピュータ)のひとつ。
      • Raspberry Pi(ラズパイ)やArduinoに似た位置づけで、電子工作や組込み開発、AI実験に使われる
      • RISC-V搭載、Linux実行可能
      • 小型で比較的安価(2025年9月時点 ¥2,300)
 

使用したコードについて

基本的には共通処理で実装しています。時間を計測する関数(get_time_sec関数)の内部のみ、OSに合わせたコードに書き換わっています。高精度単調増加クロックを採用しています。(簡単に表現するとPC内部でひたすらカウントし続けるストップウォッチのようなものを使用して時間を算出しているということ)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct {
    long long total_ops;
    long long sum;
    double elapsed_sec;
    double avg_mops;
    int completed;
} BenchResult;

BenchResult g_bench;

double get_time_sec(void) {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec + ts.tv_nsec / 1e9;
}

void report_progress(double sec_total) {
    g_bench.elapsed_sec = sec_total;
    g_bench.avg_mops = g_bench.total_ops / sec_total / 1e6;
    printf("[%.2f sec] Total ops=%lld, Avg speed=%.2f MOPS\n",
           g_bench.elapsed_sec, g_bench.total_ops, g_bench.avg_mops);
}

void report_final(double sec_total) {
    g_bench.elapsed_sec = sec_total;
    g_bench.avg_mops = g_bench.total_ops / sec_total / 1e6;
    g_bench.completed = 1;
    printf("=== Benchmark Complete ===\n");
    printf("Total ops=%lld, time=%.2f sec, Avg speed=%.2f MOPS\n",
           g_bench.total_ops, g_bench.elapsed_sec, g_bench.avg_mops);
    printf("Final sum=%lld\n", g_bench.sum);
}

int main(int argc, char *argv[]) {
    int minutes = (argc >= 2) ? atoi(argv[1]) : 1;
    if (minutes <= 0) minutes = 1;
    int duration = minutes * 60;

    g_bench.total_ops = 0;
    g_bench.sum = 0;
    g_bench.completed = 0;

    double start = get_time_sec();
    double last_report = start;

    printf("=== Integer Benchmark for %d minutes ===\n", minutes);

    while (1) {
        for (int i = 0; i < 10000; i++) {
            g_bench.sum += (i * 13) ^ (i >> 3);
        }
        g_bench.total_ops += 10000;

        double now = get_time_sec();
        double sec_total = now - start;
        double sec_since_last = now - last_report;

        if (sec_since_last >= 60.0) {
            report_progress(sec_total);
            last_report = now;
        }
        if (sec_total >= duration) {
            report_final(sec_total);
            break;
        }
    }
    return 0;
}
 

検証方法

今回も、前回と同様に、Windows環境での検証と同じプログラム・同じルールで計測を行いました。使用したプログラムの仕様を改めておさらいしておきます。

【ベンチマークプログラムの動作】

ひたすら整数の足し算やビット演算といったシンプルな計算を、任意の時間(単位:分)にわたって繰り返すプログラムです。これにより、CPUがどれだけの計算を処理できるか(MOPS: Million Operations Per Second)を測定します。
バックグラウンドで動いているアプリケーションの負荷状況により多少変化はあるかもしれませんが、おおよそ同じ条件下で実行しています。今回は3分間計測します。 なお、このベンチマークはVisual Studio 2019を使用してコンパイル・実行しています。ファイル実行時に、任意の数字を渡すことで、指定した時間(単位:分)のスコアを計測します。

前回の記事のWindows用の計測方法と同じように3分ずつ計測し、それぞれの平均速度と最終演算数が出力します。

> benchmark 3   // 3分間のスコア計測が実行されます
 

検証結果

Linux環境でのC言語ベンチマーク結果比較表

VirtualBox上のUbuntuは、Windowsほどのスペックは出ませんが、なかなかな結果が出ているように感じ取れます。また、シングルブートしているUbuntuでも、SSDではなくHDDの古いPCながら健闘しているようにも感じられます。Windows10のサポートも切れて、ただ「廃棄する」よりも、いっそ「OSのサポートが切れたのなら、Linuxマシンとして余生を過ごしてもらう」という活用方法もありそうですね!

Milk-Vについては、ほかのこの手のデバイスと比較できませんでしたので、良し悪しはわかりませんが、ラズパイなどと比較すると、実力の程がよく分かるかもしれません。※今回は用意できず検証できませんでしたがぜひお手元で^^

 

まとめ

VirtualBoxも設定によるとは思いますが、見方によっては、思ったよりホストOSのスコアからあまり劣ることなくハードウェアリソースを使用できている状況にあると言えるかもしれません。(少なくとも筆者はそう思いました)

また、古いPCでもまだまだ活躍できそうな雰囲気があるということもこの検証を通してわかりました。社内でもお古のPCをUbuntuで動かしている人が多いことは知っていたのですが、納得のできる検証結果になったと思います。UbuntuはWindowsと比べるとOS自体も比較的軽い(最近のバージョンはそれでも重くなったよねという意見もありますが)ですし、普段あまりLinuxを触らない方はこの機会にLinux用のマシンを仕立ててみては如何でしょうか?

(念の為)あくまでも、C言語の実行に関してのスコアなので、ほかのサービスが動いていたときの状況や、JavaやPythonを実行したときのことはわかりません。目安としていただければ幸いです。

WindowsやLinuxなど、環境によってこれほど性能に違いが出ることが分かりました。次回はいよいよ最終回。この計測コードを使い、私たちが提供している開発支援ツール「DT+Trace」が、プログラムの実行処理にどの程度影響(オーバーヘッド)を与えるのかを実測します。

ツールを導入する際によくいただく「動作は重くならないか?」というエンジニアの切実な問いに対し、従来の処理時間ではなく、今回の「MOPS」という別のアプローチで検証した結果をぜひご覧ください。

【連載】自作コードでC言語のベンチマーク計測#3 ~ DT+Traceドライバの実力を計測 ~

検証してきたベンチマーク環境を使い、動的テストツール「DT+Trace」のオーバーヘッドを実測。テストポイント挿入による性能低下をMOPS値で可視化し、自前ロギングとの比較や管理工数削減のメリットを技術的視点で解説します。