Main Content

Beschleunigen der BER-Simulationen mithilfe der Parallel Computing Toolbox

In diesem Beispiel wird die Parallel Computing Toolbox™ verwendet, um eine einfache QPSK-Bit-Error-Rate-(BER-)Simulation zu beschleunigen. Das System besteht aus einem QPSK-Modulator, einem QPSK-Demodulator, einem AWGN-Kanal und einem Bitfehlerratenzähler.

Legen Sie die Simulationsparameter fest.

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

Ordnen Sie den Arrays, die zum Speichern der durch die Funktion helper_qpsk_sim_with_awgn generierten Daten verwendet werden, Hauptspeicher zu.

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

Führen Sie die Simulation aus und bestimmen Sie die Ausführungszeit. Zum Bestimmen der Referenzleistung wird nur ein einziger Prozessor verwendet. Dementsprechend sollten Sie darauf achten, dass die normale for-Schleife verwendet wird.

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;

Berechnen Sie die BER.

ber1 = numErrors ./ numBits;

Führen Sie die Simulation noch einmal für den Fall aus, bei dem die Parallel Computing Toolbox verfügbar ist. Erstellen Sie einen Worker-Pool.

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

Bestimmen Sie anhand der Eigenschaft NumWorkers von pool die Anzahl der verfügbaren Worker. Die Simulation wird mit dem Bereich der Werte von $E_{b}/N_{0}$ für jeden Worker ausgeführt, anstatt jedem Worker einen einzelnen $E_{b}/N_{0}$-Punkt zuzuweisen, da die erstgenannte Methode die größte Leistungsverbesserung mit sich bringt.

numWorkers = pool.NumWorkers;

Bestimmen Sie die Länge von EbNoVec für die Verwendung in der verschachtelten parfor-Schleife. Für die richtige Variablenklassifizierung muss der Bereich einer for-Schleife, die in einem parfor verschachtelt ist, durch konstante Zahlen oder Variablen definiert sein.

lenEbNoVec = length(EbNoVec);

Ordnen Sie den Arrays, die zum Speichern der durch die Funktion helper_qpsk_sim_with_awgn generierten Daten verwendet werden, Hauptspeicher zu.

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

Führen Sie die Simulation aus und bestimmen Sie die Ausführungszeit.

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;

Berechnen Sie die BER. In diesen Fall müssen die Ergebnisse mehrerer Prozessoren kombiniert werden, um die aggregierte BER zu generieren.

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

Vergleichen Sie die BER-Werte, um zu überprüfen, ob unabhängig von der Anzahl der Worker dieselben Ergebnisse berechnet werden.

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

Wie Sie sehen, sind die BER-Kurven im Wesentlichen identisch. Abweichungen ergeben sich lediglich durch unterschiedliche Startwerte für Zufallszahlen.

Vergleichen Sie die Ausführungszeiten der einzelnen Methoden.

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