ソルバーの並列実行

parallel_solve() を使用すると、複数のソルバーやモデルに対して同時にリクエストを送ることができます。これにより、複数回の実行が必要な場合に、モデル変換やリクエストデータの処理時間、ソルバーへのネットワークアクセスによる転送時間などの隠蔽が期待出来ます。また、複数の問題を同時に実行できるソルバーに対しても、並列実行による実行効率の向上が期待出来ます。

並列実行の例

まず、solve() 関数を使用するときと同様に、モデルを構築します。

from amplify import VariableGenerator, one_hot, FixstarsClient, solve

gen = VariableGenerator()
q = gen.array("Binary", 3)

objective = q[0] * q[1] - q[2]
constraint = one_hot(q)

model = objective + constraint

次に、複数のソルバークライアントを構築します。

from amplify import FixstarsClient, DWaveSamplerClient
from datetime import timedelta

fixstars_client = FixstarsClient()
# fixstars_client.token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
fixstars_client.parameters.timeout = timedelta(milliseconds=1000)

dwave_client = DWaveSamplerClient()
# dwave_client.token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
dwave_client.parameters.num_reads = 100

parallel_solve() 関数を用いて、複数のソルバーにリクエストを送ります。parallel_solve()solve() と同様のインターフェースを持ちますが、引数にリストを与えることができます。

from amplify import parallel_solve

fixstars_result, dwave_result = parallel_solve(model, [fixstars_client, dwave_client])

上記のコードは、以下を並列で実行したのと同じ効果を持ちます。したがって、fixstars_resultdwave_result はそれぞれ Result() クラスのインスタンスです。

from amplify import solve

fixstars_result = solve(model, fixstars_client)
dwave_result = solve(model, dwave_client)

Tip

parallel_solve() にモデルのリストを渡すことで、異なるモデルを同一のソルバーで、あるいは異なるモデルを異なるソルバーで並列実行することが可能です。

model1 = objective + constraint
model2 = objective + 2 * constraint
単一のモデルを複数のソルバーで並列実行する:
result1, result2 = parallel_solve(model1, [fixstars_client, dwave_client])
複数のモデルを単一のソルバーで並列実行する:
result1, result2 = parallel_solve([model1, model2], fixstars_client)
複数のモデルを複数のソルバーで並列実行する:
result1, result2 = parallel_solve([model1, model2], [fixstars_client, dwave_client])

並列実行のパラメータ

parallel_solve()solve() と同様のキーワード引数を受け取ることができます。通常はキーワード引数は全ての並列実行で共通で使用されますが、リストを与えることで、複数のモデル、複数のソルバーと同様に、複数のキーワード引数を同時に指定することができます。この場合、それぞれのリストの要素数は同じでなければなりません。

例として、リストを用いた次のパラメータの指定は、

fixstars_result, dwave_result = parallel_solve(
    model,
    [fixstars_client, dwave_client],
    dry_run=[False, True],
    num_solves=2,
)

以下を並列で実行したのと同じ効果を持ちます。

fixstars_result = solve(model, fixstars_client, dry_run=False, num_solves=2)
dwave_result = solve(model, dwave_client, dry_run=True, num_solves=2)

ソルバーの種類や契約内容によっては、同一のソルバーに複数のリクエストを同時に送ることができない場合があります。parallel_solve()concurrency を指定することで、並列実行数の最大値を設定することができます。デフォルトは 0 で、この場合は動作させているマシンの CPU 数に応じて並列実行数が自動で決定されます。

fixstars_result, dwave_result = parallel_solve(
    model,
    [fixstars_client, dwave_client, fixstars_client, dwave_client],
    concurrency=2,
)