В этом примере показан рабочий процесс измерения BER блока Wireless HDL Toolbox™ LTE Turbo Decoder с помощью parsim для параллелизации симуляций через точки EbNo. Этот подход может использоваться для ускорения других симуляций Монте-Карло.
HDL- реализаций примеров готовых узлов часто являются сложными и занимают много времени, чтобы симулировать. В результате вычисление эффективности частоты битовой ошибки (BER) путем выполнения нескольких симуляций в различных точках ОСШ может быть очень длительным. Один из способов оптимизировать это - параллелизировать симуляции с помощью parsim
команда. The parsim
команда выполняет несколько параллельные симуляции при вызове с доступной лицензией Parallel Computing Toolbox™. Этот пример измеряет BER турбодекодера LTE. Чтобы достичь достаточной статистической точности, в декодере должно быть получено около 100 ошибок для каждого значения EbNo. Это переводится в 1e8 бит в BER 10e-6. Этот тип симуляции Монте-Карло является подходящим кандидатом для параллелизации с помощью parsim, где BER для каждой точки EbNo выполняется параллельно рабочим.
Для каждой параллельной симуляции этот пример настраивает входные данные следующим образом:
Сгенерируйте входные данные системы координат
Турбокодирование
Модуляция QPSK
Добавьте AWGN на основе значения EbNo
Демодулируйте шумные символы
Сгенерируйте мягкие решения
Мягкие решения становятся входом для LTE Turbo Decoder в 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
объект. Функция после постсимуляции назначается внутри функции до предварительной симуляции, как показано на разделе Функции до предварительной симуляции и после постсимуляции.
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);
[16-Jan-2021 00:32:26] Checking for availability of parallel pool... [16-Jan-2021 00:32:26] Starting Simulink on parallel workers... [16-Jan-2021 00:33:02] Configuring simulation cache folder on parallel workers... [16-Jan-2021 00:33:02] Loading model on parallel workers... [16-Jan-2021 00:33:14] Running simulations... [16-Jan-2021 00:36:20] Completed 1 of 24 simulation runs [16-Jan-2021 00:36:20] Completed 2 of 24 simulation runs [16-Jan-2021 00:36:20] Completed 3 of 24 simulation runs [16-Jan-2021 00:36:29] Completed 4 of 24 simulation runs [16-Jan-2021 00:36:30] Completed 5 of 24 simulation runs [16-Jan-2021 00:36:30] Completed 6 of 24 simulation runs [16-Jan-2021 00:36:37] Completed 7 of 24 simulation runs [16-Jan-2021 00:36:37] Completed 8 of 24 simulation runs [16-Jan-2021 00:36:37] Completed 9 of 24 simulation runs [16-Jan-2021 00:36:47] Completed 10 of 24 simulation runs [16-Jan-2021 00:36:47] Completed 11 of 24 simulation runs [16-Jan-2021 00:36:47] Completed 12 of 24 simulation runs [16-Jan-2021 00:36:55] Completed 13 of 24 simulation runs [16-Jan-2021 00:36:55] Completed 14 of 24 simulation runs [16-Jan-2021 00:36:55] Completed 15 of 24 simulation runs [16-Jan-2021 00:37:02] Completed 16 of 24 simulation runs [16-Jan-2021 00:37:02] Completed 17 of 24 simulation runs [16-Jan-2021 00:37:02] Completed 18 of 24 simulation runs [16-Jan-2021 00:37:09] Completed 19 of 24 simulation runs [16-Jan-2021 00:37:09] Completed 20 of 24 simulation runs [16-Jan-2021 00:37:09] Completed 21 of 24 simulation runs [16-Jan-2021 00:37:18] Completed 22 of 24 simulation runs [16-Jan-2021 00:37:18] Completed 23 of 24 simulation runs [16-Jan-2021 00:37:18] Completed 24 of 24 simulation runs [16-Jan-2021 00:37:18] 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.
Эти функции независимо генерируют входные данные и обрабатывают выходные данные для каждой симуляции, что устраняет необходимость в главном хосте для хранения данных в памяти для всех симуляций. The 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 для блока Wireless HDL LTE Turbo Decoder с помощью parsim. Если параллельный пул не используется, линейное время для выполнения симуляций составит приблизительно 16 часов. В результате параллелизации время выполнения всех симуляций сократилось до 5,4 часов, используя 3 рабочих. Этого удалось добиться, запустив симуляции в режиме Rapid Accelerator. Этот рабочий процесс может быть применен к комплексным примерам готовых узлов, которые требуют Монте-Карло или других симуляций.