はじめに
それなりに高性能なMacを持っているので、そのCPUの力を引き出してみようという試みです。(あら、でもさらに高性能な後継モデルがつい先日発表になってしまいましたね、、、)
また、この文章の内容は、筆者が所属している会社・団体とは一切関わりがありません。いわゆる「自主的な研究の成果の発表」というものです。
OpenMP
簡単に並列処理をするならOpenMPということで。
準備
OpenMP on High Sierraによると、どうやら、Macの標準のコンパイラ(clang)はOpenMPの機能をサポートしているようです。なので、コンパイラ一式からインストールしなくていいです1。が、ライブラリは入ってなかったりするようなので、その辺りの準備は必要です。(ここから先、基本的には"OpenMP on High Sierra"の内容をなぞってます。が、当然、私のOSは"High Sierra"(macOS 10.13)な訳はなく、"Sequoia"(macOS 15)です。)
brew install libomp
が、その前に"brew search"で確認したら、手元のMacではすでにlibompはインストールされているようです。libompそのものをbrewでインストールした記憶はないので、OpenMPの機能を使っているHomebrewのソフトがあって依存関係でインストールされているってことでしょうね。ということで"brew install"はしませんでした。
コンパイル
諸々適切に設定されているのなら
cc -fopenmp myprog.c
でコンパイルできるようです2が、普通はそんなことはないでしょう。ということで、以下のようにします。
cc -o myprog -Xpreprocessor -fopenmp -lomp -I"$(brew --prefix libomp)/include" -L"$(brew --prefix libomp)/lib" myprog.c
(基本的には"OpenMP on High Sierra"の真似です。ccを使ったことのある方なら、やろうとしていることは大体分かるでしょう。)
これで特にエラーも出ることなく、コンパイルできました。
実験結果
以下のプログラムで実験してみます。OpenMPでは恒例らしい円周率を求めるプログラムです。
#include <stdio.h>
#include <omp.h>
static long num_steps = 500000000;
long double step;
int main(void)
{
int i; long double x, pi, sum = 0.0;
step = 1.0 / (long double) num_steps;
#pragma omp parallel for reduction(+: sum) private (x)
for (i = 0; i < num_steps; i++) {
x = (i + 0.5) * step;
sum += 4.0 / (1.0 + x * x);
}
pi = sum * step;
printf("%.15Lf\n", pi);
return 0;
}
スレッド数は環境変数 OMP_NUM_THREADS で制御できます。まず並列化せずに実行です。
$ OMP_NUM_THREADS=1 ./pi
3.141592653589814
3.14...と円周率っぽい値3が出ているのでよしとしましょう。
では、スレッド数を変えて実行してみましょう。OMP_NUM_THREADS を1から20まで変更して実行した結果です。
real、userというのは、それぞれtimeコマンドのreal、userです。8スレッドまではuserはほぼ一定、realが順調に減っているのが分かるかと思います。ということは、全体の処理に掛かる時間はほぼ変わらないものの、処理が適切に分散されているため終了までに掛かる時間が順調に短くなっているということです。一方、9スレッドになるとuserの値が少し増えてしまっています。これは「パフォーマンス」コアが8であることに対応していると考えられます。8よりも多くのスレッドを同時に動かそうとすると、今度は「効率性」コアもスレッドの実行に参入してくるようです。「効率性」コアは「パフォーマンス」コアよりも遅いですから、全体として処理に掛かる時間が増えてしまった、ということでしょう。
お前の実力はそんなものか
いいえ、違います4。最適化オプション(-O3)すら付けてませんので。実は後からそれに気がついて、-O3を指定して同じことをやってみました。が、傾向は同じでした。(なので、改めてグラフを載せることもしません。)
今回は傾向が見られればそれで満足ですので、以上とします。(はい、私の実力はこんなものでした。)さらなる高速化を追求したい方、あとは任せた!