Запустите пользовательские учебные циклы на графическом процессоре и параллельно

Можно ускорить пользовательские учебные циклы путем работы графического процессора в параллели с помощью нескольких графических процессоров, или в кластере.

Рекомендуется обучить использование графического процессора или нескольких графических процессоров. Только используйте один центральный процессор или несколько центральных процессоров, если у вас нет графического процессора. Центральные процессоры обычно намного медленнее что графические процессоры и для обучения и для вывода. Работа одного графического процессора обычно предлагает намного лучшую эффективность, чем работа нескольких ядер процессора.

Примечание

Эта тема показывает вам, как выполнить пользовательское обучение на графических процессорах, параллельно, и в облаке. Узнать о параллели и рабочих процессах графического процессора с помощью trainNetwork функционируйте, см.:

Используя графический процессор или параллельные опции требует Parallel Computing Toolbox™. Используя графический процессор также требует поддерживаемого устройства графического процессора. Для получения информации о поддерживаемых устройствах смотрите Поддержку графического процессора Релизом (Parallel Computing Toolbox). Используя удаленный кластер также требует MATLAB® Parallel Server™.

Обучите сеть на графическом процессоре

По умолчанию пользовательские учебные циклы работают на центральном процессоре. Автоматическое использование дифференцирования dlgradient и dlfeval поддержки, работающие на графическом процессоре, когда ваши данные находятся на графическом процессоре. Чтобы запустить пользовательский учебный цикл на графическом процессоре, просто преобразуйте свои данные в gpuArray (Parallel Computing Toolbox) во время обучения.

Можно использовать minibatchqueue управлять вашими данными во время обучения. minibatchqueue автоматически готовит данные к обучению, включая пользовательскую предварительную обработку и преобразование данных к dlarray и gpuArray. По умолчанию, minibatchqueue возвращает все мини-пакетные переменные на графическом процессоре, если вы доступны. Можно выбрать который переменные возвратиться на графическом процессоре с помощью OutputEnvironment свойство.

Для примера, показывающего, как использовать minibatchqueue чтобы обучаться на графическом процессоре, смотрите, Обучат сеть Используя Пользовательский Учебный Цикл.

В качестве альтернативы можно вручную преобразовать данные в gpuArray в учебном цикле.

Чтобы легко задать среду выполнения, создайте переменную executionEnvironment это содержит любой "cpu", "gpu", или "auto".

executionEnvironment = "auto"

Во время обучения, после чтения мини-пакета, проверяют опцию среды выполнения и преобразуют данные в gpuArray при необходимости. canUseGPU функционируйте проверки на применимые графические процессоры.

if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu"
    dlX = gpuArray(dlX);
end

Обучите одну сеть параллельно

Когда вы обучаетесь параллельно, каждый рабочий обучает сеть одновременно с помощью фрагмента мини-пакета. Это означает, что необходимо объединить градиенты, потерю и любые параметры состояния после каждой итерации, согласно пропорции мини-пакета, обработанного каждым рабочим.

Можно обучаться параллельно на локальной машине, или в удаленном кластере, например, в облаке. Запустите параллельный пул в желаемых ресурсах и разделите свои данные между рабочими. Во время обучения, комбинируют градиенты, потеря и состояние после каждой итерации так, чтобы настраиваемые параметры на каждом рабочем обновились в синхронизации. Для примера, показывающего, как выполнить пользовательское обучение параллельно, смотрите, Обучат сеть параллельно с Пользовательским Учебным Циклом

Настройте параллельную среду

Рекомендуется обучить использование графического процессора или нескольких графических процессоров. Только используйте один центральный процессор или несколько центральных процессоров, если у вас нет графического процессора. Центральные процессоры обычно намного медленнее что графические процессоры и для обучения и для вывода. Работа одного графического процессора обычно предлагает намного лучшую эффективность, чем работа нескольких ядер процессора.

Настройте параллельную среду, которую вы хотите использовать перед обучением. Запустите параллельный пул с помощью желаемых ресурсов. Для обучения с помощью нескольких графических процессоров начните параллельный пул со стольких же рабочих сколько доступные графические процессоры. Для лучшей эффективности MATLAB автоматически присваивает различный графический процессор каждому рабочему.

Если вы используете свою локальную машину, можно использовать canUseGPU и gpuDeviceCount (Parallel Computing Toolbox), чтобы определить, имеете ли вы графические процессоры в наличии. Например, чтобы проверять доступность графических процессоров и начать параллельный пул со стольких же рабочих сколько доступные графические процессоры, используйте следующий код:

if canUseGPU
    executionEnvironment = "gpu";
    numberOfGPUs = gpuDeviceCount("available");
    pool = parpool(numberOfGPUs);
else
    executionEnvironment = "cpu";
    pool = parpool;
end

Если при запуске использование удаленного кластера, например, кластера в облаке, начните параллельный пул со стольких же рабочих сколько количество графических процессоров на машину, умноженную на количество машин.

Для получения дополнительной информации о выборе определенных графических процессоров смотрите, Выбирают Particular GPUs to Use for Training.

Задайте мини-пакетные данные о размере и разделе

Задайте мини-пакетный размер, который вы хотите использовать во время обучения. Для обучения графического процессора методические рекомендации должны увеличить мини-пакетный размер линейно с количеством графических процессоров, для того, чтобы сохранить рабочую нагрузку на каждом графическом процессоре постоянной. Например, если вы - обучение на одном графическом процессоре с помощью мини-пакетного размера 64, и вы хотите масштабировать до обучения с помощью четырех графических процессоров того же типа, можно увеличить мини-пакетный размер до 256 так, чтобы каждый графический процессор процессы 64 наблюдения на итерацию.

Можно использовать следующий код, чтобы увеличить мини-пакетный размер количеством рабочих, где N количество рабочих в вашем параллельном пуле.

if executionEnvironment == "gpu"
    miniBatchSize = miniBatchSize .* N
end

Если вы хотите использовать мини-пакетный размер что не точно делимый количеством рабочих в вашем параллельном пуле, то распределите остаток на рабочих.

workerMiniBatchSize = floor(miniBatchSize ./ repmat(N,1,N));
remainder = miniBatchSize - sum(workerMiniBatchSize);
workerMiniBatchSize = workerMiniBatchSize + [ones(1,remainder) zeros(1,N-remainder)]

В начале обучения переставьте свои данные. Разделите свои данные так, чтобы у каждого рабочего был доступ к фрагменту мини-пакета. Чтобы разделить datastore, используйте partition функция.

Можно использовать minibatchqueue управлять данными по каждому рабочему во время обучения. minibatchqueue автоматически готовит данные к обучению, включая пользовательскую предварительную обработку и преобразование данных к dlarray и gpuArray. Создайте minibatchqueue на каждом рабочем, использующем разделенный datastore. Установите MiniBatchSize свойство с помощью мини-пакетных размеров, вычисленных для каждого рабочего.

В начале каждой учебной итерации используйте gop (Parallel Computing Toolbox) функция, чтобы проверять, что весь рабочий minibatchqueue объекты могут возвратить данные. Если у какого-либо рабочего заканчиваются данные, учебные остановки. Если ваш полный мини-пакетный размер не является точно делимым количеством рабочих, и вы не отбрасываете частичные мини-пакеты, у некоторых рабочих могут закончиться данные перед другими.

Запишите свой учебный код в spmd Блок (Parallel Computing Toolbox), так, чтобы учебный цикл выполнился на каждом рабочем.

spmd
    % Reset and shuffle the datastore.
    reset(augimdsTrain);
    augimdsTrain = shuffle(augimdsTrain);

    % Partition datastore.
    workerImds = partition(augimdsTrain,N,labindex);

    % Create minibatchqueue using partitioned datastore on each worker
    workerMbq = minibatchqueue(workerImds,...
        "MiniBatchSize",workerMiniBatchSize(labindex),...
        "MiniBatchFcn",@preprocessMiniBatch);

    ...

    for epoch = 1:numEpochs

        % Reset and shuffle minibatchqueue on each worker.
        shuffle(workerMbq);
                
        % Loop over mini-batches.
        while gop(@and,hasdata(workerMbq))

            % Custom training loop
            ...
            
        end
        ...
    end
end

Совокупные градиенты

Чтобы гарантировать, что сеть на каждом рабочем извлекает уроки из всех данных и не только данных по тому рабочему, агрегируйте градиенты и используйте агрегированные градиенты, чтобы обновить сеть на каждом рабочем.

Например, предположите, что вы - обучение сеть dlnet, использование градиентов модели функционирует modelGradients. Ваш учебный цикл содержит следующий код для оценки градиента, потери и статистики по каждому рабочему:

[workerGradients,dlworkerLoss,workerState] = dlfeval(@modelGradients,dlnet,dlworkerX,workerY);
dlworkerX и workerY предиктор и истинный ответ на каждом рабочем, соответственно.

Чтобы агрегировать градиенты, используйте взвешенную сумму. Задайте функцию помощника, чтобы суммировать градиенты.

function gradients = aggregateGradients(dlgradients,factor)
    gradients = extractdata(dlgradients);
    gradients = gplus(factor*gradients);
end

В учебном цикле использовать dlupdate применять функцию к градиентам каждого настраиваемого параметра.

workerGradients.Value = dlupdate(@aggregateGradients,workerGradients.Value,{workerNormalizationFactor});

Совокупная потеря и точность

Чтобы найти сетевую потерю и точность, например, построить их во время обучения контролировать процесс обучения, агрегировали значения потери и точности на всех рабочих. Как правило, агрегированное значение является суммой значения на каждом рабочем, взвешенном пропорцией мини-пакета, используемого на каждом рабочем. Чтобы агрегировать потери и точность каждая итерация, вычислите весовой коэффициент для каждого рабочего и использования gplus (Parallel Computing Toolbox), чтобы суммировать значения на каждом рабочем.

workerNormalizationFactor = workerMiniBatchSize(labindex)./miniBatchSize;
loss = gplus(workerNormalizationFactor*extractdata(dlworkerLoss));
accuracy = gplus(workerNormalizationFactor*extractdata(dlworkerAccuracy));

Совокупная статистика

Если ваша сеть содержит слои, которые отслеживают статистику ваших обучающих данных, таких как слои нормализации партии., то необходимо агрегировать статистику через всех рабочих после каждой учебной итерации. Выполнение так гарантирует, что сеть изучает статистические данные, которые являются представительными для целого набора обучающих данных.

Можно идентифицировать слои, которые содержат информацию о статистике перед обучением. Например, если вы используете dlnetwork со слоями нормализации партии. можно использовать следующий код, чтобы найти соответствующие слои.

batchNormLayers = arrayfun(@(l)isa(l,'nnet.cnn.layer.BatchNormalizationLayer'),dlnet.Layers);
batchNormLayersNames = string({dlnet.Layers(batchNormLayers).Name});
state = dlnet.State;
isBatchNormalizationStateMean = ismember(state.Layer,batchNormLayersNames) & state.Parameter == "TrainedMean";
isBatchNormalizationStateVariance = ismember(state.Layer,batchNormLayersNames) & state.Parameter == "TrainedVariance";
Задайте функцию помощника, чтобы агрегировать статистику, которую вы используете. Слои нормализации партии. отслеживают среднее значение и отклонение входных данных. Можно агрегировать среднее значение на всех рабочих, использующих взвешенное среднее. Вычислить агрегированное отклонение sc2, используйте формулу следующей формы.

sc2=1Mj=1Nmj(sj2+(x¯jx¯c)2)

N является общим количеством рабочих, M является общим количеством наблюдений в мини-пакете, mj является количеством наблюдений, обработанных на j th рабочий, x¯j и sj2 среднее значение и статистика отклонения, вычисленная на того рабочего, и x¯c агрегированное среднее значение через всех рабочих.

function state = aggregateState(state,factor,...
    isBatchNormalizationStateMean,isBatchNormalizationStateVariance)

    stateMeans = state.Value(isBatchNormalizationStateMean);
    stateVariances = state.Value(isBatchNormalizationStateVariance);

    for j = 1:numel(stateMeans)
        meanVal = stateMeans{j};
        varVal = stateVariances{j};
        
        % Calculate combined mean
        combinedMean = gplus(factor*meanVal);
               
        % Calculate combined variance terms to sum
        varTerm = factor.*(varVal + (meanVal - combinedMean).^2);        
        
        % Update state
        stateMeans{j} = combinedMean;
        stateVariances{j} = gplus(varTerm);
    end

    state.Value(isBatchNormalizationStateMean) = stateMeans;
    state.Value(isBatchNormalizationStateVariance) = stateVariances;
end

В учебном цикле используйте функцию помощника, чтобы обновить состояние слоев нормализации партии. с объединенным средним значением и отклонением.

dlnet.State = aggregateState(workerState,workerNormalizationFactor,...
                isBatchNormalizationStateMean,isBatchNormalizationStateVariance);

Постройте результаты во время обучения

Если вы хотите построить результаты во время обучения, можно отправить данные от рабочих клиенту, использующему DataQueue объект.

Чтобы легко указать, что график должен идти или прочь, создайте переменную plots это содержит любой "training-progress" или "none".

plots = "training-progress";

Перед обучением инициализируйте DataQueue и анимированная линия с помощью animatedline функция.

if plots == "training-progress"
    figure
    lineLossTrain = animatedline('Color',[0.85 0.325 0.098]);
    ylim([0 inf])
    xlabel("Iteration")
    ylabel("Loss")
    grid on
end
Создайте DataQueue объект. Использование afterEach вызывать функцию помощника displayTrainingProgress каждый раз данные отправляются от рабочего клиенту.
Q = parallel.pool.DataQueue;
displayFcn = @(x) displayTrainingProgress(x,lineLossTrain);
afterEach(Q,displayFcn);
displayTrainingProgress функция помощника содержит код, используемый, чтобы добавить точки в анимированную линию и отобразить учебную эпоху и длительность.
function displayTrainingProgress (data,line)
     addpoints(line,double(data(3)),double(data(2)))
     D = duration(0,0,data(4),'Format','hh:mm:ss');
     title("Epoch: " + data(1) + ", Elapsed: " + string(D))
     drawnow
end

В учебном цикле, в конце каждой эпохи, используют DataQueue отправить обучающие данные от рабочих клиенту. В конце каждой итерации агрегированная потеря является тем же самым на каждом рабочем, таким образом, можно отправить данные от одного рабочего.

% Display training progress information.
if labindex == 1
   data = [epoch loss iteration toc(start)];
   send(Q,gather(data)); 
end

Обучите несколько сетей параллельно

Чтобы обучить несколько сетей параллельно, запустите параллельный пул в своих желаемых ресурсах и использовании parfor (Parallel Computing Toolbox), чтобы обучить одну сеть на каждом рабочем.

Можно запуститься локально или использование удаленного кластера. Используя удаленный кластер требует MATLAB Parallel Server. Для получения дополнительной информации о ресурсах кластера управления, смотрите, Обнаруживают Кластеры и Профили Кластера Использования (Parallel Computing Toolbox). Если вы имеете несколько графических процессоров и хотите исключить некоторых из обучения, можно выбрать GPU, который вы используете, чтобы обучаться на. Для получения дополнительной информации о выборе определенных графических процессоров смотрите, Выбирают Particular GPUs to Use for Training.

Можно изменить сеть или параметры обучения на каждом рабочем, чтобы выполнить развертки параметра параллельно. Например, в networks массив dlnetwork объекты, можно использовать код следующей формы, чтобы обучить несколько различных сетей с помощью тех же данных.

parpool ("local",numNetworks);

parfor idx = 1:numNetworks
    iteration = 0;  
    velocity = [];

    % Allocate one network per worker 
    dlnet = networks(idx)

    % Loop over epochs.
    for epoch = 1:numEpochs
        % Shuffle data.
        shuffle(mbq);
    
        % Loop over mini-batches.
        while hasdata(mbq)
            iteration = iteration + 1;

            % Custom training loop
            ...

        end     
        
    end

    % Send the trained networks back to the client.
    trainedNetworks{idx} = dlnet;
end
После parfor концы, trainedNetworks содержит получившиеся сети, обученные рабочими.

Постройте результаты во время обучения

Чтобы контролировать процесс обучения на рабочих, можно использовать DataQueue передать данные обратно от рабочих.

Чтобы легко указать, что график должен идти или прочь, создайте переменную plots это содержит любой "training-progress" или "none".

plots = "training-progress";

Перед обучением инициализируйте DataQueue и анимированные линии с помощью animatedline функция. Создайте подграфик для каждой сети, вы - обучение.

if plots == "training-progress"
    f = figure;
    f.Visible = true;
    for i=1:numNetworks
        subplot(numNetworks,1,i)
        xlabel('Iteration');
        ylabel('loss');
        lines(i) = animatedline;
    end
end
Создайте DataQueue объект. Использование afterEach вызывать функцию помощника displayTrainingProgress каждый раз данные отправляются от рабочего клиенту.
Q = parallel.pool.DataQueue;
displayFcn = @(x) displayTrainingProgress(x,lines);
afterEach(Q,displayFcn);
displayTrainingProgress функция помощника содержит код, используемый, чтобы добавить точки в анимированные линии.
function displayTrainingProgress (data,lines)
     addpoints(lines(1),double(data(4)),double(data(3)))
     D = duration(0,0,data(5),'Format','hh:mm:ss');
     title("Epoch: " + data(2) + ", Elapsed: " + string(D))
     drawnow limitrate nocallbacks
end

В учебном цикле, в конце каждой итерации, используют DataQueue отправить обучающие данные от рабочих клиенту. Отправьте parfor индекс цикла, а также учебная информация так, чтобы точки были добавлены к правильной линии для каждого рабочего.

% Display training progress information.
data = [idx epoch loss iteration toc(start)];
send(Q,gather(data)); 

Используйте Experiment Manager, чтобы обучаться параллельно

Можно использовать Experiment Manager, чтобы запустить пользовательские учебные циклы параллельно. Можно или запустить несколько следов одновременно или запустить одно испытание во время с помощью параллельных ресурсов.

Чтобы запустить несколько испытаний одновременно с помощью одного параллельного рабочего для каждого испытания, настройте пользовательский учебный эксперимент разрешение опции Use Parallel прежде, чем запустить эксперимент.

Чтобы запустить одно испытание во время с помощью нескольких параллельных рабочих, задайте параллельную среду в обучении эксперименту, функционируют и используют spmd блокируйтесь, чтобы обучить сеть параллельно. Для получения дополнительной информации об обучении одной сети параллельно с пользовательским учебным циклом смотрите, Обучают Одну Сеть параллельно.

Для получения дополнительной информации об обучении в параллели с помощью Experiment Manager смотрите Использование Experiment Manager, чтобы Обучаться параллельно.

Смотрите также

(Parallel Computing Toolbox) | (Parallel Computing Toolbox) | (Parallel Computing Toolbox) | |

Похожие темы