Этот пример использует 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
. Мы предоставляем дополнительный аргумент 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
, и обновляем график. Мы прерываем цикл рано, если пользователь нажимает кнопку отмены на waitbar, или 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