使用 parfeval 玩 21 点游戏
此示例使用 Parallel Computing Toolbox™ 玩一种叫做 blackjack(也称为 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。我们为 timeout 方法提供可选参量 fetchNext,以便在没有新结果时它能够快速返回。
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);

收集并显示可用的结果
我们通过循环调用 fetchNext 来收集和显示结果,直到我们看到 numPlayers 的结果。当 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