BER Simulations with Parallel Computing Toolbox
This example shows how to improve the execution speed of communication systems involving BER simulations. To improve the performance of these systems, one of the available options is to parallelize the simulations. This example introduces the usage of the Parallel Computing Toolbox™ in BER simulations. It presents two possible ways of parallelizing BER simulations and recommends the better method.
License Check and Opening a Parallel Pool
This section checks for the availability of Parallel Computing Toolbox. If available, it opens a parallel pool of workers and assigns the maximum number of available workers in the pool to the variable numWorkers. If not available it assigns numWorkers = 1, in which case the example runs on a single core.
[licensePCT,~] = license( 'checkout','Distrib_Computing_Toolbox'); if ( licensePCT && ~isempty(ver('parallel'))) if isempty(gcp('nocreate')) parpool; end pool = gcp; numWorkers = pool.NumWorkers; else numWorkers = 1; end
Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 6).
Initialization
This example parallelizes the Spatial Multiplexing example to demonstrate the usage of Parallel Computing Toolbox. The following are the parameters needed to simulate this example.
EbNo = 1:2:11; % Eb/No in dB N = 2; % Number of transmit antennas M = 2; % Number of receive antennas modOrd = 2; % constellation size = 2^modOrd numBits = 1e6; % Number of bits numErrs = 100; % Number of errors lenEbNo = length(EbNo); % Create a local random stream to be used for data generation for % repeatability. Use the combined multiple recursive generator since it % supports substreams. hStr = RandStream('mrg32k3a'); % Setting the random stream [berZF,berMMSE] = deal(zeros(lenEbNo,3)); [nerrsZF,nbitsZF,nerrsMMSE,nbitsMMSE] = deal(zeros(numWorkers,lenEbNo));
Parallelizing Across the Eb/No Range
The first method parallelizes across the Eb/No range, where one worker processes a single Eb/No value. Here the performance is limited by the time required to process the highest Eb/No value.
simIndex = 1; str = 'Across the Eb/No range'; disp('Performing BER simulations with one worker processing one Eb/No value ...');
Performing BER simulations with one worker processing one Eb/No value ...
tic parfor idx = 1:lenEbNo [BER_ZF,BER_MMSE] = simBERwithPCT(N,M,EbNo,modOrd, ... idx,hStr,numBits,numErrs); berZF(idx,:) = BER_ZF(idx,:); berMMSE(idx,:) = BER_MMSE(idx,:); end timeRange = toc; clockBERwithPCT(simIndex,timeRange,timeRange,str);
Parallelizing Across the Number of Workers in the Parallel Pool
The second method parallelizes across the number of available workers, where each worker processes the full Eb/No range. However, each worker counts (total errors/numWorkers) errors before proceeding to the next Eb/No value. This method uses all available cores equally efficiently.
simIndex = simIndex + 1; str = 'Across the number of available workers'; seed = 0:numWorkers-1; disp('Performing BER simulations with each worker processing the entire range ...');
Performing BER simulations with each worker processing the entire range ...
tic parfor n = 1:numWorkers hStr = RandStream('mrg32k3a','Seed',seed(n)); for idx = 1:lenEbNo [BER_ZF,BER_MMSE] = simBERwithPCT(N,M,EbNo,modOrd, ... idx,hStr,numBits/numWorkers,numErrs/numWorkers); nerrsZF(n,idx) = BER_ZF( idx,2); nbitsZF(n,idx) = BER_ZF( idx,3); nerrsMMSE(n,idx) = BER_MMSE(idx,2); nbitsMMSE(n,idx) = BER_MMSE(idx,3); end end bZF = sum(nerrsZF,1)./sum(nbitsZF,1); bMMSE = sum(nerrsMMSE,1)./sum(nbitsMMSE,1); timeWorker = toc;
Below are the results obtained on a Windows® 7, 64-bit, Intel® Xeon® CPU W3550, ~3.1GHz, 12.288GB RAM machine using four cores. The table shows the performance comparison of the above methods. We see that the second method performs better than the first. These are the results obtained on a single run and may vary from run to run.
-------------------------------------------------------------------------------------------- Type of Parallelization | Elapsed Time (sec)| Speedup Ratio 1. Across the Eb/No range | 89.7366 | 1.0000 2. Across the number of available workers | 28.4443 | 3.1548 --------------------------------------------------------------------------------------------
The plot below shows the BER curves obtained for the zero forcing (ZF) and minimum mean squared error (MMSE) receivers using the different parallelization methods.
plotBERwithPCT(EbNo,berZF(:,1),berMMSE(:,1),bZF,bMMSE);
To generate a performance comparison table for your machine, uncomment the following line of code and run this entire script.
% clockBERwithPCT(simIndex,timeRange,timeWorker,str);
Appendix
The following functions are used in this example: