Ускорение симуляций BER Используя Parallel Computing Toolbox

Этот пример использует Parallel Computing Toolbox, чтобы ускорить простую, симуляцию частоты ошибок по битам (BER) QPSK. Система состоит из модулятора QPSK, демодулятора QPSK, канала AWGN и небольшого счетчика коэффициента ошибок.

Установите параметры симуляции.

EbNoVec = 5:8;     % Eb/No values in dB
totalErrors = 200; % Number of bit errors needed for each Eb/No value
totalBits = 1e7;   % Total number of bits transmitted for each Eb/No value

Выделите память массивам, используемым, чтобы хранить данные, сгенерированные функцией, helper_qpsk_sim_with_awgn.

[numErrors, numBits] = deal(zeros(length(EbNoVec),1));

Запустите симуляцию и определите время выполнения. Только один процессор будет использоваться, чтобы определить базовую эффективность. Соответственно, заметьте, что нормальный цикл for используется.

tic
for idx = 1:length(EbNoVec)
    errorStats = helper_qpsk_sim_with_awgn(EbNoVec,idx, ...
        totalErrors,totalBits);
    numErrors(idx) = errorStats(idx,2);
    numBits(idx) = errorStats(idx,3);
end
simBaselineTime = toc;

Вычислите BER.

ber1 = numErrors ./ numBits;

Повторно выполните симуляцию для случая, в котором Parallel Computing Toolbox доступен. Создайте пул рабочих.

pool = gcp;
assert(~isempty(pool), ['Cannot create parallel pool. '...
  'Try creating the pool manually using ''parpool'' command.'])
Starting parallel pool (parpool) using the 'local' profile ...
Connected to the parallel pool (number of workers: 6).

Определите количество доступных рабочих от NumWorkers свойство pool. Симуляция запускает область значений$E_{b}/N_{0}$ значений по каждому рабочему вместо того, чтобы присвоить одну$E_{b}/N_{0}$ точку каждому рабочему, когда бывший метод обеспечивает самое большое повышение производительности.

numWorkers = pool.NumWorkers;

Определите длину EbNoVec для использования во вложенном parfor цикл. Для соответствующей переменной классификации область значений цикла for вкладывается в parfor должен быть задан постоянными числами или переменными.

lenEbNoVec = length(EbNoVec);

Выделите память массивам, используемым, чтобы хранить данные, сгенерированные функцией, helper_qpsk_sim_with_awgn.

[numErrors,numBits] = deal(zeros(length(EbNoVec),numWorkers));

Запустите симуляцию и определите время выполнения.

tic
parfor n = 1:numWorkers
    for idx = 1:lenEbNoVec
        errorStats = helper_qpsk_sim_with_awgn(EbNoVec,idx, ...
            totalErrors/numWorkers,totalBits/numWorkers);
        numErrors(idx,n) = errorStats(idx,2);
        numBits(idx,n) = errorStats(idx,3);
    end
end
simParallelTime = toc;

Вычислите BER. В этом случае результаты нескольких процессоров должны быть объединены, чтобы сгенерировать совокупный BER.

ber2 = sum(numErrors,2) ./ sum(numBits,2);

Сравните значения BER, чтобы проверить, что те же результаты получены независимые от количества рабочих.

semilogy(EbNoVec',ber1,'-*',EbNoVec',ber2,'-^')
legend('Single Processor','Multiple Processors','location','best')
xlabel('Eb/No (dB)')
ylabel('BER')
grid

Вы видите, что кривые BER являются по существу тем же самым с любым отклонением, являющимся из-за отличающихся seed случайных чисел.

Сравните времена выполнения для каждого метода.

fprintf(['\nSimulation time = %4.1f sec for one worker\n', ...
    'Simulation time = %4.1f sec for multiple workers\n'], ...
    simBaselineTime,simParallelTime)
fprintf('Number of processors for parfor = %d\n', numWorkers)
Simulation time = 39.9 sec for one worker
Simulation time =  9.8 sec for multiple workers
Number of processors for parfor = 6
Для просмотра документации необходимо авторизоваться на сайте