Этот пример показывает рабочий процесс, чтобы измерить BER Турбо Декодера LTE HDL Toolbox с помощью parsim, чтобы параллелизировать симуляции через точки EbNo. Этот подход может использоваться, чтобы ускорить другие симуляции Монте-Карло.
Реализации HDL примеров готовых узлов являются часто комплексными и занимают много времени, чтобы моделировать. В результате выяснение производительности частоты ошибок по битам (BER) путем выполнения нескольких симуляций в различных точках ОСШ может быть очень трудоемким. Один способ оптимизировать это состоит в том, чтобы параллелизировать симуляции с помощью parsim команды. parsim команда запускает несколько симуляций параллельно, когда названо доступной лицензией Parallel Computing Toolbox™. Этот пример измеряет BER Турбо Декодера HDL LTE. Чтобы достигнуть достаточной статистической точности, приблизительно 100 ошибок должны быть получены в декодере для каждого значения EbNo. Это переводит в 1e8 биты в BER 10e-6. Этот тип симуляции Монте-Карло является подходящим кандидатом, чтобы параллелизировать использование parsim, где BER для каждой точки EbNo выполняется на рабочих параллельно.
Для каждой параллельной симуляции этот пример настраивает входные данные можно следующим образом:
Сгенерируйте кадры входных данных;
Турбо кодирует;
QPSK модулирует;
Добавьте AWGN на основе значения EbNo;
Демодулируйте шумные символы;
Сгенерируйте мягкие решения.
Мягкие решения становятся входом к Турбо Декодеру HDL LTE в Simulink®. Декодируемые биты турбо сравниваются с переданными битами, чтобы вычислить BER. Каждая параллельная симуляция передает результаты обратно в основной хост.
Общее количество информационных битов для каждой точки EbNo
, bitsPerEbNo
, разделено по нескольким симуляциям, заданным parsimPerEbNo
. Таким образом каждая симуляция запускает биты bitsPerParsim
для одной точки EbNo
. Общим количеством симуляций является length(EbNo)*parsimPerEbNo
. Этот пример сконфигурирован, чтобы запустить только небольшое количество битов в демонстрационных целях. В действительном сценарии необходимо запустить достаточное число выборок через декодер для точной меры BER в более высоких точках EbNo
. При выборе этих параметров считайте ресурсы памяти доступными на хосте. Большой набор входных данных на симуляцию или большое количество рабочих мог привести к, замедляются или исчерпание памяти. Структура simParam
содержит параметры, требуемые для каждой симуляции. Эта структура отправляется в симуляции на более позднем этапе.
EbNo = 0:0.1:1.1; bitsPerEbNo = 1e5; %1e8; parsimPerEbNo = 2; %10; bitsPerParsim = ceil(bitsPerEbNo/parsimPerEbNo); simParam.blkSize = 6144; simParam.turboIterations = 6; simParam.numFrames = ceil(bitsPerParsim/simParam.blkSize); % frames per simulation simParam.modScheme = 'QPSK'; simParam.bps = 2; % bits per symbol tailBits = 4; % encoder property simParam.encoderRate = simParam.blkSize/(3*(simParam.blkSize+tailBits)); % rate 1/3 Turbo code simParam.samplesizeIn = floor(1/simParam.encoderRate); % 3 samples in at a time simParam.inframeSize = simParam.samplesizeIn*(simParam.blkSize+tailBits); model = 'LTEHDLTurboDecoderBERExample'; open_system(model);
Запустите локальный параллельный пул с минимума 1 и максимума maxNumWorkers
. Если лицензия Parallel Computing Toolbox™ не будет доступна, симуляции будут сериализированы. Фактический размер пула зависит от количества доступных ядер. Каждый параллельный рабочий присвоен одно ядро, на котором запускается независимый сеанс MATLAB®.
maxNumWorkers = 3;
pool = parpool('local', [1 maxNumWorkers]);
Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 3).
Предварительно выделите объект parsim содержать данные, требуемые для каждой симуляции. Объект может также включать указатели на функции, которые модель вызывает прежде или после симуляции. Сеанс MATLAB®, на котором parsim выполняется действия как основной хост. Основной хост ответственен за запуск симуляций на рабочих, отправку необходимых данных каждому рабочему и получения результатов.
parsimIn(1:length(EbNo)*parsimPerEbNo) = Simulink.SimulationInput(model);
Реплицируйте точки EbNo
, чтобы настроить симуляции parsimPerEbNo
.
repEbNo = repmat(EbNo,parsimPerEbNo,1); repEbNo = repEbNo(:);
Минимизация передачи данных рабочим улучшает производительность и устойчивость основного хоста. Поэтому этот пример генерирует входные данные в модели, вместо того, чтобы передать большой набор входных данных каждому рабочему. Входные данные сгенерированы с помощью функции перед симуляцией, presimGenInput
и вычисление BER также выполняются в функции постсимуляции, postsimOutput
. Эти указатели на функцию присвоены каждому объекту SimulationInput
. Функция постсимуляции присвоена в функции перед симуляцией как показано в разделе Pre-Simulation и Post-Simulation Functions.
for noiseRatio = 1:length(repEbNo) % Calculate the noise variance. EsNo = repEbNo(noiseRatio) + 10*log10(simParam.bps); snrdB = EsNo + 10*log10(simParam.encoderRate); noiseVar = 1./(10.^(snrdB/10)); % Use random but reproducible data. seed = noiseRatio; % For Rapid Accelerator mode, set the simulation % stop time before compilation. parsimIn(noiseRatio) = parsimIn(noiseRatio).setModelParameter('StopTime',num2str(simParam.numFrames)); % Set pre-simulation function. parsimIn(noiseRatio) = parsimIn(noiseRatio).setPreSimFcn(@(simIn) presimGenInput(simIn,noiseVar,seed,simParam)); end
Запустите и покажите прогресс симуляций в командном окне. В конце симуляций результаты передают обратно в основной хост в массиве структур, parsimOut
, с одной записью, созданной на симуляцию. Если симуляции завершены, закройте параллельный пул.
parsimOut = parsim(parsimIn,'ShowProgress','on','StopOnError','on'); delete(pool);
[15-Jan-2019 09:54:10] Checking for availability of parallel pool... [15-Jan-2019 09:54:41] Starting Simulink on parallel workers... [15-Jan-2019 09:55:12] Configuring simulation cache folder on parallel workers... [15-Jan-2019 09:55:14] Loading model on parallel workers... [15-Jan-2019 09:56:02] Running simulations... Analyzing and transferring files to the workers ...done. [15-Jan-2019 09:59:03] Completed 1 of 24 simulation runs [15-Jan-2019 09:59:03] Completed 2 of 24 simulation runs [15-Jan-2019 09:59:03] Completed 3 of 24 simulation runs [15-Jan-2019 09:59:12] Completed 4 of 24 simulation runs [15-Jan-2019 09:59:13] Completed 5 of 24 simulation runs [15-Jan-2019 09:59:13] Completed 6 of 24 simulation runs [15-Jan-2019 09:59:21] Completed 7 of 24 simulation runs [15-Jan-2019 09:59:21] Completed 8 of 24 simulation runs [15-Jan-2019 09:59:21] Completed 9 of 24 simulation runs [15-Jan-2019 09:59:29] Completed 10 of 24 simulation runs [15-Jan-2019 09:59:29] Completed 11 of 24 simulation runs [15-Jan-2019 09:59:29] Completed 12 of 24 simulation runs [15-Jan-2019 09:59:38] Completed 13 of 24 simulation runs [15-Jan-2019 09:59:38] Completed 14 of 24 simulation runs [15-Jan-2019 09:59:38] Completed 15 of 24 simulation runs [15-Jan-2019 09:59:45] Completed 16 of 24 simulation runs [15-Jan-2019 09:59:45] Completed 17 of 24 simulation runs [15-Jan-2019 09:59:45] Completed 18 of 24 simulation runs [15-Jan-2019 09:59:53] Completed 19 of 24 simulation runs [15-Jan-2019 09:59:53] Completed 20 of 24 simulation runs [15-Jan-2019 09:59:53] Completed 21 of 24 simulation runs [15-Jan-2019 10:00:01] Completed 22 of 24 simulation runs [15-Jan-2019 10:00:01] Completed 23 of 24 simulation runs [15-Jan-2019 10:00:01] Completed 24 of 24 simulation runs [15-Jan-2019 10:00:01] Cleaning up parallel workers... Parallel pool using the 'local' profile is shutting down.
Извлеките значения BER от массива структур. Объединитесь результаты BER для каждого EbNo
указывают и находят средний BER на точку EbNo
.
BER = [parsimOut(:).BER]; BER = transpose(reshape(BER,parsimPerEbNo,length(BER)/parsimPerEbNo)); avgBER = mean(BER,2); semilogy(EbNo,avgBER,'-o'); grid; xlabel('Eb/No (dB)'); ylabel('Bit Error Rate');
График ниже показов результаты измерения BER с bitsPerEbNo
= 1e8.
Эти функции независимо генерируют входные данные и выходные данные процесса для каждой симуляции, которая избавляет от необходимости основной хост хранить данные в памяти для всех симуляций. Функция presimGenInput
генерирует входные биты, затем кодирует, модулирует и преобразовывает их в мягкие решения. Чтобы сделать входные кадры и параметры доступными для модели, они присвоены как переменные в глобальной рабочей области с помощью функции setVariable
.
function simIn = presimGenInput(simIn,noiseVar,seed,simParam) rng(seed); % Preallocate arrays for speed. txBits = zeros(simParam.blkSize,simParam.numFrames,'int8'); inFrames = zeros(simParam.inframeSize,simParam.numFrames,'single'); % Generate input frames, turbo encode, modulate and add noise % based on noise variance. for currentFrame = 1:simParam.numFrames txBits(:,currentFrame) = randi([0 1],simParam.blkSize,1); codedData = lteTurboEncode(txBits(:,currentFrame)); txSymbols = lteSymbolModulate(codedData,simParam.modScheme); noise = (sqrt(noiseVar/2))*complex(randn(size(txSymbols)),randn(size(txSymbols))); rxSymbols = txSymbols + noise; inFrames(:,currentFrame) = lteSymbolDemodulate(rxSymbols,simParam.modScheme,'Soft'); end % Set up parameters for Frame to Samples block to serialize data. % Leave sufficient gap between frames. simParam.idleCyclesBetweenSamples = 0; halfIterationLatency = (ceil(simParam.blkSize/32)+3)*32; % window size = 32 algFrameDelay = 2*simParam.turboIterations*halfIterationLatency+(simParam.inframeSize/simParam.samplesizeIn); simParam.idleCyclesBetweenFrames = algFrameDelay; % Assign variables to global workspace. simIn = simIn.setVariable('inFrames',inFrames); simIn = simIn.setVariable('simParam',simParam); % Set post-simulation function and send required data. simIn = simIn.setPostSimFcn(@(simOut) postsimOutput(simOut,txBits,simParam)); end
Функция постсимуляции получает выходные параметры симуляции и вычисляет BER. Результаты хранятся в структуре results
, который parsim возвращает как parsimOut
.
function results = postsimOutput(out, txBits, simParam) decodedOutValid = out.decodedOut(out.validOut); results.numErrors = sum(xor(txBits(:),decodedOutValid)); results.BER = results.numErrors/(simParam.numFrames*simParam.blkSize); end
Этот пример показал, как эффективно измерить кривую BER для Турбо Декодера HDL LTE с помощью parsim. Если бы параллельный пул не используется, линейное время, чтобы завершить симуляции составило бы приблизительно 16 часов. В результате распараллеливания время, чтобы запустить все симуляции свелось к 5,4 часам, с помощью 3 рабочих. Это было достигнуто путем выполнения симуляций в Быстром Режиме Accelerator, использования лицензии Simulink Coder™. Этот рабочий процесс может быть применен, чтобы объединить примеры готовых узлов, которые требуют Монте-Карло или других симуляций.