Previous ToC Next

115. 「京」でのプログラム最適化

石山君・似鳥君の宇宙論的 N 体計算用 TreePM コードは「京」で 53%(だっけ)と いう驚異的な実行効率をだしたわけですが、これは2008年には天文台の Cray XT4 で 2048 コアまで十分スケールするプログラムを開発済であった石山君と、 重力計算カーネルの部分で理論的に可能な性能の 97% という効率を引き出す ことに成功した似鳥君の才能と努力によるものです。

普通のプログラムを普通に「京」で実行した時の効率は、典型的には 1-2% で あるようです。これは、大雑把には以下のように理解できます。

従って、「京」で実効性能をあげるために絶対的に必要なことは、最内側ループ が並列実行可能であるとコンパイラに認識させることになります。つまり、 「ベクトル化可能なコードを書く」ということです。

昨日某君のコードを似鳥君が見て、いくつかの計算量が多いループについてこ う変形、というのを指示しているところを見物させてもらう機会がありました。 実際の主な作業は、コードを書換えてコンパイラにかけ、メッセージをみてベ クトル化、アンロールされているかどうかを確認することであり、コンパイラ がベクトル化とアンロールの両方に成功したというようになったら、アセンブ ラ出力をチェックして問題のループに対応する部分で確かにSIMD 命令がでてい るかどうかを確認、それから実行してその部分の詳細プロファイルをとり、4命 令発行が十分多くなっていることを確認する、というような手順になります。

コードの具体的な書換えの例を以下に2つほど。実際のソースは今手元にない ので感じだけです。なので、実際にこの形のものというわけではない です。

例えばループ内で計算結果や配列のデータによっ て処理が変わる、例えば

  do i=1, n
     if (a(i) .gt. 0.0) then
        b(i)=xxx
     else
        b(i)=zzz
     endif
  enddo
といったループの時に、これはベクトル化可能であっていいはずなのですがベ クトル化してくれていないことがあります。そういう場合には

  do i=1, n
     if (a(i) .gt. 0.0) then
        btmp=xxx
     else
        btmp=zzz
     endif
     b(i)=btmp
  enddo
と、if 文の中をより簡単な形にしてやるとコンパイラが構造を認識してくれたりするので、 そういうようなことをやってみるわけです。いや、何が簡単かわからない、と 思う方が多いと思いますが、書換えたあとは左辺値が if ブロックと else ブ ロックで同じスカラー変数ですから、配列要素(同じものさしているのですが)で ある最初の形よりコンパイラに優しくなっています。

また、 if then else endif の代 わりに可能な場合には最大値関数を使うのも有効とのことでした。

あと、F90の配列記法を使った文、つまり、ベクトル化可能と明示的に書いてあ るものが性能がでなくて、 DO ループにしたらちゃんと性能がでるようになったとかいう例もありました。

こういうのは25年前にベクトル化コンパイラを使っていた私にはなんだかとて もみおぼえがある書換えで、結局、近代的な SIMD マシンで SIMD ユニットの 性能がでるためにはまずはベクトル化できるように書くということになります。 で、そのためにはコンパイラが理解できるようにソースを書換える必要がある わけです。必要な書換えは、25年前にベクトル化コンパイラ相手にやっていた のとあまりかわりません。

ベクトル化コンパイラの相手、というのは正直なところあまりやりたくない仕 事です。コンパイラに理解できるようにするためだけにコードを良く分からな い形に書換えていく必要があるし、それは要するにコンパイラのベクトル可能 性認識アルゴリズムに合わせる、というもので、しかもそれがどういうものか の明確な規則はドキュメントに完全な形では存在せず、 試行錯誤して 結果をみる必要があるからです。

さらに、それだけでは不足、というのが最近のマシンの厄介なところで、 キャッシュメモリはちゃんと使えているか、といったことが次には問題に なってくるわけです。

25年前に比べて、MPI で並列化して書くというだけで恐ろしく大変になってい るのに、1ノード内でのチューニングもベクトル化的なことはしないといけな いしキャッシュも考えないといけないわけで、なかなか手に負えない 代物になってきているのを実感しました。

つーか、その、結局ベクトル化するならハードウェアもベクトル命令にして SIMD の幅をもっと広くしてしまったほうが効率よさそう、と思うわけですが、 この場合にメモリアクセスをどうするかという問題があるよね、というのは7年前に 7 で書いたことでした。 「京」では、私が当時書いたように、 SIMD ユニットは2語にして、 128ビット境界でなくて64ビット境界でのロードもできるようにして問題をあ る程度回避しています。この先どうするかは AVX についていきます、という のが文部科学省の会議での富士通の人の発言によれば今後の方向のようです。

Previous ToC Next