Блэк джек 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. Мы предоставляем дополнительный аргумент 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