Этот пример показывает рабочий процесс, чтобы измерить 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
'points'. При выборе этих параметров считайте ресурсы памяти доступными на хосте. Большой набор входных данных на симуляцию или большое количество рабочих мог привести к, замедляются или исчерпание памяти. Структура 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);
[07-Mar-2019 14:33:22] Checking for availability of parallel pool... [07-Mar-2019 14:34:51] Starting Simulink on parallel workers... [07-Mar-2019 14:35:51] Configuring simulation cache folder on parallel workers... [07-Mar-2019 14:35:53] Loading model on parallel workers... [07-Mar-2019 14:36:45] Running simulations... Analyzing and transferring files to the workers ...done. [07-Mar-2019 14:39:00] Completed 1 of 24 simulation runs [07-Mar-2019 14:39:00] Completed 2 of 24 simulation runs [07-Mar-2019 14:39:00] Completed 3 of 24 simulation runs [07-Mar-2019 14:39:13] Completed 4 of 24 simulation runs [07-Mar-2019 14:39:13] Completed 5 of 24 simulation runs [07-Mar-2019 14:39:13] Completed 6 of 24 simulation runs [07-Mar-2019 14:39:22] Completed 7 of 24 simulation runs [07-Mar-2019 14:39:22] Completed 8 of 24 simulation runs [07-Mar-2019 14:39:22] Completed 9 of 24 simulation runs [07-Mar-2019 14:39:31] Completed 10 of 24 simulation runs [07-Mar-2019 14:39:31] Completed 11 of 24 simulation runs [07-Mar-2019 14:39:31] Completed 12 of 24 simulation runs [07-Mar-2019 14:39:40] Completed 13 of 24 simulation runs [07-Mar-2019 14:39:40] Completed 14 of 24 simulation runs [07-Mar-2019 14:39:40] Completed 15 of 24 simulation runs [07-Mar-2019 14:39:49] Completed 16 of 24 simulation runs [07-Mar-2019 14:39:49] Completed 17 of 24 simulation runs [07-Mar-2019 14:39:49] Completed 18 of 24 simulation runs [07-Mar-2019 14:39:57] Completed 19 of 24 simulation runs [07-Mar-2019 14:39:57] Completed 20 of 24 simulation runs [07-Mar-2019 14:39:57] Completed 21 of 24 simulation runs [07-Mar-2019 14:40:07] Completed 22 of 24 simulation runs [07-Mar-2019 14:40:07] Completed 23 of 24 simulation runs [07-Mar-2019 14:40:07] Completed 24 of 24 simulation runs [07-Mar-2019 14:40:07] 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. Этот рабочий процесс может быть применен, чтобы объединить примеры готовых узлов, которые требуют Монте-Карло или других симуляций.