Intel CPUとAMD CPUの混在による問題に直面した話

Created
Aug 7, 2023 6:42 AM
Tags
CPU
Editor
Tomoya Kabe
image

チーフエンジニアの加辺です。

今日は珍しいトラブルに出会ったので紹介します。

起こった問題

ある環境ではEC2によりサーバを運用しており、アプリケーションをデプロイサーバでビルドし、その成果物をアプリケーションサーバへコピーすることでデプロイとしていました。

ここで新規サーバを作成していたところ、一部のアプリケーションサーバで見慣れないエラーが発生し、アプリケーションが起動しないという事象が確認されました。調べたところ、デプロイサーバはt3、アプリケーションサーバはt3aファミリーが利用されていることがわかり、アプリケーションサーバをt3ファミリーへ変更したところ、問題が発生しなくなることが分かりました。

さて、これはどのような機序によるものでしょうか。

調査

記事タイトルで答えをほとんど書いてしまっていますし、t3, t3aを知っていれば明らかですが、これはIntelとAMDの違いです。

本アプリケーションはRubyで記述されており、Rubyは以下のようなログを書き出していました。適宜抜粋します。

0x00007f1758f39b10番地に不正な命令があるとのことです。このログだけを見ると libffi に原因があるように見えます。

ところが実際にこの番地が何者かを確認してみると、libffiではありませんでした。

sasscがmapされていました。さらにこの共有オブジェクトの中身を調べ、どんな命令なのか見てみます。

0x00007f1758f39b10 - 0x7f1758eb6000 = 0x83B10です。

ということで、VMOVDQU64という命令であることがわかりました。

新しい命令

これを調べると、AVX-512の命令であることがわかりました。

アライメントされていないメモリー位置からパックド int64 要素をロードします。

通常はAMD64でもIntel64の命令はサポートされているはず…と思ったのですが、AVX-512の命令は2021年3月に発表されたZen-4以降でようやくサポートされたばかりだったようです。

This would make "Zen 4" the first AMD microarchitecture to support AVX-512.

Intel64でsasscをコンパイルした際にAVX-512の命令が入ってしまい、それをAMD64で動かそうとした結果だったようです。

とりうる対応

いくつもありますが、例として以下のような方法が考えられます。

  1. CPU familyをIntel64に揃える(AVX-512はSkylake-SP以降)
  2. デプロイサーバをAMD64にする(今回の問題の逆パターンも考えられ、問題が起こる可能性が0になるわけではない)
  3. ビルドするとき(今回であればgemをbundleinstall)にgccのオプションに --disable-avx512 を付ける
  4. AWSがAMD EPYCのプロセッサを全てZen-4以降に置き換えてくれるのを待つ
  5. 各サーバでnativeなバイナリをビルドするようにする

今回、手っ取り早くできる&コストが抑えられる対応として、2つ目の方法をとりました。