Main Content

La traduction de cette page n'est pas à jour. Cliquez ici pour voir la dernière version en anglais.

Accélérer les simulations BER en utilisant Parallel Computing Toolbox

Cet exemple utilise Parallel Computing Toolbox™ pour accélérer une simulation simple de taux d’erreur bit (BER) d'une modulation QPSK. Ce système comprend un modulateur QPSK, un démodulateur QPSK, un canal AWGN et un compteur de taux d’erreur bit.

Configurez les paramètres de simulation.

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

Attribuez de la mémoire aux tableaux utilisés pour stocker les données générées par la fonction, helper_qpsk_sim_with_awgn.

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

Exécutez la simulation et déterminez l’heure d'exécution. Un seul processeur sera utilisé pour déterminer les performances de la base de référence. Par conséquent, notez que la boucle for normale est utilisée.

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;

Calculez le BER.

ber1 = numErrors ./ numBits;

Réexécutez la simulation dans le cas où Parallel Computing Toolbox est disponible. Créez un pool de workers.

pool = gcp;
assert(~isempty(pool), ['Cannot create parallel pool. '...
  'Try creating the pool manually using ''parpool'' command.'])

Déterminez le nombre de workers disponibles à partir de la propriété NumWorkers de pool. La simulation s'exécute sur la plage des valeurs de $E_{b}/N_{0}$ sur chaque worker au lieu d’attribuer à chaque worker un point $E_{b}/N_{0}$ unique, car la première méthode offre la meilleure amélioration de performance.

numWorkers = pool.NumWorkers;

Déterminez la longueur de EbNoVec pour une utilisation dans la boucle parfor imbriquée. Pour une classification de variables correcte, la plage d'exécution d’une boucle for imbriquée dans un parfor doit être définie par des nombres ou des variables constantes.

lenEbNoVec = length(EbNoVec);

Attribuez de la mémoire aux tableaux utilisés pour stocker les données générées par la fonction, helper_qpsk_sim_with_awgn.

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

Exécutez la simulation et déterminez l’heure d'exécution.

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;

Calculez le BER. Dans ce cas, les résultats provenant de processeurs multiples doivent être associés pour générer le BER global.

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

Comparez les valeurs BER pour vérifier que les mêmes résultats sont obtenus indépendamment du nombre de workers.

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

On peut voir que les courbes BER sont essentiellement les mêmes, toute variance étant due à des valeurs de départ de nombres aléatoires différentes.

Comparez les temps d’exécution pour chaque méthode.

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 = 24.6 sec for one worker
Simulation time =  6.1 sec for multiple workers
Number of processors for parfor = 6