Этот пример использует 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