BogoMips

BogoMips（"bogus"=「いんちきの」+ MIPS）とは、Linuxカーネルのブート時にCPU速度をビジーループを使って非科学的に測定した結果である。その定義としてよく言われるのは「プロセッサが全く無駄な処理を1秒間に何百万回できるか」であるエリック・レイモンドとジェフ・マッケンジーが1990年代初めごろインターネットで発言したが、起源は追跡不能。。

BogoMipsは、あるプロセッサがクロック周波数やキャッシュの有無から見て妥当な性能を示しているかを判断するのに使える。異なる種類のCPU間での性能比較には使えない。

 歴史 
1993年、ラルス・ビルゼニウスが comp.os.linux にLinuxカーネルにBogoMipsが導入された理由を次のように投稿している。

MIPSは Millions of Instructions Per Second（百万命令毎秒）の略だ。プロセッサの速度を求める手段である。そのような測定法の多くと同様、適切に利用されるより乱用されることが多い（異機種のコンピュータ間でMIPS値を正しく比較するのは非常に難しい）。
BogoMipsはリーナス自身の発案である。Linuxカーネル 0.99.11（1993年7月11日）はタイミングループを必要としていた（待ち時間が非常に短いのでループする以外のウェイト手段を採用できなかった）。タイミングループはプロセッサの処理速度の違いを較正しなければならない。そこでカーネルでブート時にビジーループを実際に回してみて、そのコンピュータがどの程度の速度かを測定することにした。"Bogo" は "bogus"（いんちきの）に由来し、それが一種のごまかしであることを意味している。BogoMipsの値はプロセッサ速度の一種の指標を与えるが、あまりにも非科学的なので BogoMips 以外に呼び様がない。
ブート時にその値を表示する理由は2つある。第一にそのコンピュータのキャッシュや加速手段が正しく機能しているかをチェックするのに使える。第二にリーナスはこのニュースを聞いて混乱している人々を見かけたときにくすくす笑うのが大好きである。

 BogoMipsの正しい比較 
非常に大まかではあるが、BogoMipsの相対値を計算する式を以下の表で示す。この相対値は各CPUが使用されていた当時のLinuxでのBogoMips値に基づくものである。clock は、そのCPUのクロック周波数。インデックスは、クロック周波数当たりの BogoMips の係数が Intel 386DX と同じCPUを1とした相対値である。

システム相対値インデックスIntel 8088 clock × 0.0040.02Intel/AMD 386SX clock × 0.140.8Intel/AMD 386DX clock × 0.181 (これを 1 とした値)Motorola 68030clock × 0.251.4Cyrix/IBM 486clock × 0.341.8Intel Pentiumclock × 0.402.2Intel486 clock × 0.502.8AMD 5x86clock × 0.502.8MIPS R4000/R4400clock × 0.502.8ARM9clock × 0.502.8Motorola 8081clock × 0.653.6Motorola 68040clock × 0.673.7PowerPC 603clock × 0.673.7Intel StrongARMclock × 0.663.7NexGen Nx586clock × 0.754.2PowerPC 601clock × 0.844.7Alpha 21064/21064Aclock × 0.995.5Alpha 21066/21066Aclock × 0.995.5Alpha 21164/21164Aclock × 0.995.5Intel Pentium Proclock × 0.995.5Cyrix Cx5x86/6x86 clock × 1.005.6Intel Pentium II/IIIclock × 1.005.6AMD K7/Athlonclock × 1.005.6Intel Celeronclock × 1.005.6Intel Itaniumclock × 1.005.6MIPS R4600clock × 1.005.6Hitachi SH-4clock × 1.005.6Raspberry Pi (Model B)clock × 1.005.6Intel Itanium 2clock × 1.498.3Alpha 21264clock × 1.9911.1VIA Centaurclock × 1.9911.1AMD K5/K6/K6-2/K6-IIIclock × 2.0011.1AMD Duron/Athlon XPclock × 2.0011.1AMD Sempronclock × 2.0011.1UltraSparc IIclock × 2.0011.1Intel Pentium MMXclock × 2.0011.1Intel Pentium 4clock × 2.0011.1Intel Pentium Mclock × 2.0011.1Intel Core Duoclock × 2.0011.1Intel Core 2 Duoclock × 2.0011.1Intel Atom N455clock × 2.0011.1Centaur C6-2clock × 2.0011.1PowerPC 604/604e/750clock × 2.0011.1Intel Pentium III Coppermineclock × 2.0011.1Intel Pentium III Xeonclock × 2.0011.1Motorola 68060clock × 2.0111.2Intel Xeon MP (32-bit)（ハイパースレッディング）clock × 3.9722.1IBM S390データが不十分 Intel ARMデータが不十分 

BogoMipsの詳細な情報と数百の測定値が BogoMips Mimi-Howto にある。

Linuxカーネル 2.2.14 以降、キャッシュの設定がBogoMipsの計算前に行われるようになった。BogoMipsの計算方法は変わっていないので、当時の Pentium 系CPU以降ではBogoMips値が約2倍になっている。このBogoMips値の変化は実際のプロセッサ性能には何の効果もない。

 BogoMIPSの計算 
Linuxカーネル (2.6.x) での BogoMips は /usr/src/linux/init/calibrate.c というソースファイルで実装されている。Linuxカーネルが使用するタイミングパラメータ loops_per_jiffy （Jiffy についてはジフィを参照）を計算で求めている。まず、ソースコードのコメントを示す。

<nowiki>
 /*
   * A simple loop like
   *  while ( jiffies < start_jiffies+1)
   *    start = read_current_timer();
   * will not do. As we don't really know whether jiffy switch
   * happened first or timer_value was read first. And some asynchronous
   * event can happen between these two events introducing errors in lpj.
   *
   * So, we do
   * 1. pre_start <- When we are sure that jiffy switch hasn't happened
   * 2. check jiffy switch
   * 3. start <- timer value before or after jiffy switch
   * 4. post_start <- When we are sure that jiffy switch has happened
   *
   * Note, we don't know anything about order of 2 and 3.
   * Now, by looking at post_start and pre_start difference, we can
   * check whether any asynchronous event happened or not
   */
</nowiki>

loops_per_jiffy はudelay関数（μ秒単位の遅延）とndelay関数（ナノ秒単位の遅延）の実装で使われている。これらの関数は一部のドライバがハードウェアを待つのに必要としている。これらはビジーウェイトを採用しているので、使用するとカーネルは実質的にブロックされる。i386アーキテクチャの場合 /usr/src/linux/arch/i386/lib/delay.c にて delay_loop が次のように実装されている。

/* simple loop based delay: */
static void delay_loop(unsigned long loops)
{
  int d0;

  __asm__ __volatile__(
    "\tjmp 1f\n"
    ".align 16\n"
    "1:\tjmp 2f\n"
    ".align 16\n"
    "2:\tdecl %0\n\tjns 2b"
    :"=&a" (d0)
    :"0" (loops));
}

これをCの擬似コードで書き直すと、次のようになる。

static void delay_loop(long loops)
{
  long d0 = loops;
  do {
    --d0;
  } while (d0 >= 0);
}

BogoMipsのさらなる詳細と（ほとんどが古いが）数百のBogoMips値が BogoMips mini-Howto にある。

 脚注 

 外部リンク 
 BogoMips についてのよくある質問
 BogoMips Mini-Howto, V38（英語）
 The Jargon File: BogoMIPS（英語）
 BogoMips cpu rate

Category:Linux
Category:ベンチマーク