メインコンテンツまでスキップ

AIエージェントの並列化は速くなるのか - テストを同時に回すと遅くなった実測

公開読了約8分

この記事では、AIコーディングエージェントを複数同時に走らせたときに、本当に速くなるのかを実測から解説します。テストを2パッケージ同時に回したときは、1つずつ順番に回した12秒に対して21秒かかりました。並列化して縮むのは、テストの実行時間ではありません。

この記事はこんな人にオススメ
  • 並列化して本当に速くなるのかを実測で知りたい人
  • エージェントを並列にしたのに速くなった実感が無い人
  • 何を並列にして何を並列にしないかを決めたい人
  • 並列実行で落ちたテストの切り分け方を知りたい人

テストの並列化の計測結果​

エージェントを複数走らせると、それぞれが自分の担当分のテストを回すことになります。まずそこを測りました。

パッケージ単位のテストを、1つずつ順番に回した場合と同時に回した場合で計測しました(Flutter 3.47.2 / CPU 10コアのマシン、各3回の中央値)。

パッケージ数順番に同時に
212秒21秒
434秒37秒

テストの並列化は速くならず、同時に回したほうが遅くなりました。

テストの実行ツールは、何も指定しなければCPUの空きを自分で使い切るように動きます。それを複数同時に走らせると、CPUの取り合いになって互いに待たされます。

パッケージ数が増えると差は縮まりましたが、2点の計測では理由を切り分けられていません。

読み書きに消える時間​

時間が消えていたのは、エージェントが読んで考える部分です。例えば次のような形で消えます。

  • 「無い」と思って読み始めたものが既に実装済みで、20〜40分読んでから「あった」と分かる、というのが繰り返し起きます
  • 全部書き終えてから、触れてはいけない領域のリスト(denylist)に当たり、最初の5分で grep できた事実に最後の5分でようやく気づきました

遅れた原因は、問題の難しさよりも、1つずつ順番に読んでいた進め方にあります。並列化する対象としては、こちらに意味があります。

  • エージェントの読み書き: 分単位で積み上がるので、ここを並列化する
  • テスト・ビルド: 秒単位で終わり、しかも既に内部で並列なので、重ねても得るものがない

全体チェック待ちの窓​

調査を流すのに安全な枠はひとつだけあり、それが全体チェックの待ち時間です。

全体チェックはリポジトリ全体を対象にCIと同じチェック一式を走らせるもので、筆者の環境では20〜30分かかります。チェックが走っている間、ツリーは読み取り専用として扱われるので、読むだけの調査エージェントであれば同時に走らせても衝突しません。

この窓は普段すべて捨てていますが、ツリーは読めるが触れないという状態は、調査を流すのに向いた条件です。

ただし、境界を計算していない段階では、そこ以外に安全な枠がありません。同時に実行して本当に速くなるかは筆者もまだ計っていませんが、全体チェックに20〜30分かかるリポジトリでは、調査を並列化するだけで得られる効果が大半を占める可能性があります。

この効果は全体チェックが長い環境でだけ成り立ちます。数分で終わるなら、窓は無いものとして扱います。

調査エージェントには、上の失敗にそのまま対応する3問を答えさせます。

  1. 既に実装済みか: エラーメッセージのような症状ではなく、仕組みの名前で grep する
  2. denylistに当たるか: 呼び出し元まで辿る
  3. 再現テストが書けるか: 書けるなら既存のどのテストに足せるか
調査の戻り値は「結論と path:line」に絞る

調査エージェントにファイルの中身を貼らせると、親が読む量が調査ログで膨らみます。返させるのは結論と path:line だけにして、必要になった箇所は親が読み直す形にします。並列化で節約した時間を、親が読む量を増やして失わないための設計です。

同時に走らせる本数は、トラブルが起きない範囲として4本に置いています。この数字に理論的な根拠はなく、実際に起きたトラブルから決まった上限です。

並列で落ちたときの切り分け​

並列実行は目に見えて複雑なので、失敗したときに原因を全部そこだと決めたくなります。4本を同時に走らせている状態で1つのパッケージのテストが落ち、共有リソースの競合を疑いました。

単独で走らせたところ同じように落ちました。原因は並列とは無関係で、期待する結果を保存したファイルが実装の変更に追いついていない、以前から分かっていた問題です。

切り分けずに結論していたら、動いている仕組みのほうを誤って捨てていました。

並列で落ちたら、まず単独で走らせます。 切り分けは次の順序で進めます。

  1. 失敗したパッケージを単独で再実行する
  2. 単独でも落ちるなら、原因は並列とは無関係。そのテスト自体を見る
  3. 単独では通るなら、そこで初めて共有リソースを疑う。どのパスが誰の担当外だったかを git status --porcelain の記録から辿る

この順序を踏まないと、並列化の仕組みは「なんとなく不安定」という理由で捨てられます。捨てる判断そのものが正しいこともありますが、根拠は切り分けの結果に置きます。

まとめ​

この記事では、AIコーディングエージェントを複数同時に走らせたときに本当に速くなるのかを、実測から解説しました。テストを2パッケージ同時に回した場合、1つずつ順番に回した12秒に対して21秒かかっています。テストの実行ツールは何も指定しなければCPUを使い切るので、重ねると取り合いになります。

分単位で積み上がっていたのは、エージェントが読んで考える時間のほうです。並列化する対象として意味があるのはこちらで、全体チェックの待ち時間がその安全な枠になります。並列で落ちたときは、まず単独で走らせて切り分けます。

並列にして効くと分かったら、次は何を同時に触ってよいかを決めることになります。作業ツリーや .git は誰が呼び出してもひとつしかないので、担当の分け方はAIエージェントを並列で走らせる境界にまとめています。


参考リンク: