このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
Parfeval を用いたブラックジャック
この例では Parallel Computing Toolbox™ を使用して、カード ゲームのブラックジャック (「21」とも呼ばれる) をプレイします。別々に数千のゲーム数をプレイする多数のプレーヤーを同時にシミュレートし、利得の統計を表示します。この例では、parfeval
を使用してワーカーの並列プールで非同期的にシミュレーションを実行します。こうすることで、結果が使用可能になった時点で結果の表示を更新できます。
関連する例:
この例のコードは以下の関数に含まれています。
function paralleldemo_blackjack_parfeval
逐次的問題の解析
ブラックジャックのプレーヤーは互いに独立しているため、並列でシミュレートできます。これを行うには、問題をいくつかの小さな関数評価に分割します。最大で numPlayers
回のシミュレーションを実行し、各プレーヤーはブラックジャックを numHands
回プレイします。結果が使用可能になったらすぐにプロットし、経過時間が maxSimulationTime
秒を超えるか、ユーザーが実行をキャンセルした場合はシミュレーションを終了します。
numPlayers = 100; numHands = 5000; maxSimulationTime = 20;
作業を個々の関数評価に分割
関数 parfeval
を呼び出して、並列プールのワーカーにおけるシミュレーションの評価を要求します。並列プールは必要に応じて自動的に作成されます。関数 parfeval
は parallel.Future
オブジェクトを返します。このオブジェクトを使用して、結果が使用可能になった時点でこれらの結果にアクセスします。詳細については、pctdemo_task_blackjack のコードを参照してください。
for idx = numPlayers:-1:1 futures(idx) = parfeval(@pctdemo_task_blackjack, 1, numHands, 1); end % Create an onCleanup to ensure we do not leave any futures running when we exit % this example. cancelFutures = onCleanup(@() cancel(futures));
結果収集と進行状況監視の設定
並列プール ワーカーはただちに pctdemo_task_blackjack
の実行を開始し、結果が使用可能になったら、fetchNext
メソッドを使用してすぐにその収集と表示を行うことができます。resultsSoFar
を使用して結果を累積します。配列 completed
を更新して futures
のどの要素が完了したかを示し、カウンター numCompleted
をインクリメントします。fetchNext
メソッドに任意引数 timeout
を指定して、使用可能な新しい結果がない場合はすぐにメソッドが戻るようにします。
resultsSoFar = zeros(numHands, numPlayers); % Allocate space for all results completed = false(1, numPlayers); % Has a given future completed yet timeout = 2; % fetchNext timeout in seconds numCompleted = 0; % How many simulations have completed fig = pctdemo_setup_blackjack(1); % Create a figure to display results % Build a waitbar with a cancel button, using appdata to track % whether the cancel button has been pressed. hWaitBar = waitbar(0, 'Blackjack progress', 'CreateCancelBtn', ... @(src, event) setappdata(gcbf(), 'Cancelled', true)); setappdata(hWaitBar, 'Cancelled', false);
使用可能になった結果の収集と表示
numPlayers
件の結果が表示されるまで、fetchNext
をループで呼び出して結果の収集と表示を行います。fetchNext
が新たな結果を返したら、この結果を resultsSoFar
に割り当て、配列 completed
と numCompleted
カウンターを更新し、プロットを更新します。ユーザーがウェイトバーのキャンセル ボタンを押した場合、または maxSimulationTime
が経過した場合は、ループを早期に中止します。
startTime = clock(); while numCompleted < numPlayers % fetchNext blocks execution until one element of futures has completed. It % then returns the index into futures of the element that has now completed, % and the results from execution. [completedIdx, resultThisTime] = fetchNext(futures, timeout); % If fetchNext timed out returning an empty completedIdx, do not attempt to % process results. if ~isempty(completedIdx) numCompleted = numCompleted + 1; % Update list of completed futures. completed(completedIdx) = true; % Fill out portion of results. resultsSoFar(:, completedIdx) = resultThisTime; % Update plot. pctdemo_plot_blackjack(fig, resultsSoFar(:, completed), false); end % Check to see if we have run out of time. timeElapsed = etime(clock(), startTime); if timeElapsed > maxSimulationTime fprintf('Simulation terminating: maxSimulationTime exceeded.\n'); break; end % Check to see if the cancel button was pressed. if getappdata(hWaitBar, 'Cancelled') fprintf('Simulation cancelled.\n'); break; end % Update the waitbar. fractionTimeElapsed = timeElapsed / maxSimulationTime; fractionPlayersCompleted = numCompleted / numPlayers; fractionComplete = max(fractionTimeElapsed, fractionPlayersCompleted); waitbar(fractionComplete, hWaitBar); end fprintf('Number of simulations completed: %d\n', numCompleted); % Now the simulation is complete, we can cancel the futures and delete % the waitbar. cancel(futures); delete(hWaitBar);
Simulation terminating: maxSimulationTime exceeded. Number of simulations completed: 74
end