2025/08/11 04:59 Going Faster Than Memcpy

ロボ子、今日はメモリコピーの最適化について話すのじゃ!

メモリコピーですか、博士。最適化の余地があるのですね。

そう!大量のバイナリデータをコピーする時、時間がかかる問題があったらしいのじゃ。そこで、色々な方法を試したみたいだぞ。

具体的にはどのような方法を試されたのですか?

`memcpy`を調べて、`__memmove_avx_unaligned_erms`がAVXを使って一度に32バイトをコピーしているのを発見したらしいのじゃ。`memcpy`と`memmove`の違いも重要だぞ。

`memcpy`はコピー元とコピー先が重ならないことを前提として、`memmove`は重なりを許容するのですね。他にどのような実装方法を試されたのですか?

`REP MOVSB`でERMSの単純なバージョンを実装したり、アラインメントされたAVX、ストリームAVX、さらにはプリフェッチまで試したみたいじゃ。

ループのアンローリングやマルチスレッディングも試されたのですね。Shadesmar APIというのも気になります。

Shadesmar APIは、カスタムメモリコピーロジックを統合するために`Copier`を導入したものらしいのじゃ。`cudaMemcpy`みたいにクロスデバイスで使えるようにしたかったみたいだぞ。

なるほど。ベンチマークの結果はどうだったのでしょう?

`std::memcpy`が一番良かったらしいのじゃ!ハードウェアアーキテクチャに最適化されていて、アラインメントも気にしなくていいからだぞ。

`std::memcpy`が最適とは意外でした。ストリーミングプリフェッチコピーは大きなコピーに最適とのことですが、それ以外は`std::memcpy`で十分なのですね。

そういうことじゃ!パフォーマンスが重要な場合は、アラインメント要件のある非ジェネリック実装を検討する余地はあるみたいじゃがな。

勉強になります。ちなみに、アンローリングはどの程度パフォーマンスを向上させるのでしょうか?

アンローリングは大体5〜10%くらいパフォーマンスを上げてくれるみたいじゃ。でも、`std::memcpy`には敵わないのじゃ。

結論としては、特別な理由がない限り`std::memcpy`を使うのが無難ということですね。

その通り!ちなみに、このコードは`dragons.h`に入ってるらしいぞ。まるで、ドラゴンの宝物みたいじゃな!

確かに、メモリコピーの最適化は奥が深いですね。まるで迷宮のようです。

そうじゃな。でも、`std::memcpy`という最強の魔法があれば、どんな迷宮も怖くないぞ!

博士、今日はありがとうございました。とても勉強になりました。

どういたしまして。最後に一つ、メモリコピーが速すぎて、コピーしたはずのデータがまだ存在しないというジョークはどうじゃ?

それはまるで、シュレディンガーの猫ですね!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。