Мелкие нейронные сети с параллелью и вычислением графического процессора

Примечание

Для глубокого обучения, параллели и поддержки графического процессора является автоматическим. Можно обучить сверточную нейронную сеть (CNN, ConvNet) или длинные краткосрочные сети памяти (сети LSTM или BiLSTM) использование trainNetwork функционируйте и выберите среду выполнения (центральный процессор, графический процессор, мультиграфический процессор и параллель) использование trainingOptions.

Обучение параллельно, или на графическом процессоре, требует Parallel Computing Toolbox™. Для получения дополнительной информации о глубоком обучении для графических процессоров и параллельно, смотрите Глубокое обучение для Больших данных на центральных процессорах, графических процессорах, параллельно, и в Облаке.

Режимы параллелизма

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

Parallel Computing Toolbox, когда используется в сочетании с Deep Learning Toolbox™, позволяет обучению нейронной сети и симуляции использовать в своих интересах каждый режим параллелизма.

Например, следующее показывает стандартный однопоточный сеанс обучения и симуляции:

[x, t] = bodyfat_dataset;
net1 = feedforwardnet(10);
net2 = train(net1, x, t);
y = net2(x);

Два шага, которые можно параллелизировать на этом сеансе, являются вызовом train и неявный вызов sim (где сеть net2 называется как функция).

В Deep Learning Toolbox можно разделить любые данные, такие как x и t в коде предыдущего примера, через выборки. Если x и t содержите только одну выборку каждый, нет никакого параллелизма. Но если x и t содержите сотни или тысячи выборок, параллелизм может обеспечить и скорость и проблемные преимущества размера.

Распределенные вычисления

Parallel Computing Toolbox позволяет обучению нейронной сети и симуляции натыкаться на несколько ядер процессора на одном PC, или через несколько центральных процессоров на нескольких компьютерах в сети с помощью MATLAB® Parallel Server™.

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

Чтобы управлять кластерными конфигурациями, используйте Кластерного менеджера по Профилю в меню Environment вкладки MATLAB Home Parallel > Manage Cluster Profiles.

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

pool = parpool
Starting parallel pool (parpool) using the 'local' profile ... connected to 4 workers.

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

pool.NumWorkers
   4

Теперь можно обучить и симулировать нейронную сеть с данными, разделенными выборкой через всех рабочих. Для этого установите train и sim параметр 'useParallel' к 'yes'.

net2 = train(net1,x,t,'useParallel','yes')
y = net2(x,'useParallel','yes')

Используйте 'showResources' аргумент, чтобы проверить, что вычисления натыкались на несколько рабочих.

net2 = train(net1,x,t,'useParallel','yes','showResources','yes');
y = net2(x,'useParallel','yes','showResources','yes');

MATLAB указывает, какие ресурсы использовались. Например:

Computing Resources:
Parallel Workers
  Worker 1 on MyComputer, MEX on PCWIN64
  Worker 2 on MyComputer, MEX on PCWIN64
  Worker 3 on MyComputer, MEX on PCWIN64
  Worker 4 on MyComputer, MEX on PCWIN64

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

Однако вы можете хотеть выполнить это деление данных вручную если:

  • Проблемный размер является слишком большим для хоста - компьютера. Вручную определение элементов Составных значений последовательно позволяет намного большим проблемам быть заданными.

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

Следующий код последовательно создает серию случайных наборов данных и сохраняет их, чтобы разделить файлы:

pool = gcp;
for i=1:pool.NumWorkers
  x = rand(2,1000);
  save(['inputs' num2str(i)],'x');
  t = x(1,:) .* x(2,:) + 2 * (x(1,:) + x(2,:));
  save(['targets' num2str(i)],'t');
  clear x t
end

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

Теперь можно загрузить наборы данных последовательно через параллельных рабочих, и обучить и симулировать сеть на Составных данных. Когда train или sim вызван Составными данными, 'useParallel' аргумент автоматически установлен в 'yes'. При использовании Составных данных сконфигурируйте вход сети и выходные параметры, чтобы совпадать с одним из наборов данных вручную с помощью configure функция перед обучением.

xc = Composite;
tc = Composite;
for i=1:pool.NumWorkers
  data = load(['inputs' num2str(i)],'x');
  xc{i} = data.x;
  data = load(['targets' num2str(i)],'t');
  tc{i} = data.t;
  clear data
end
net2 = configure(net1,xc{1},tc{1});
net2 = train(net2,xc,tc);
yc = net2(xc);

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

for i=1:pool.NumWorkers
  yi = yc{i}
end

Объединенный Составное значение в одно локальное значение, если вы не обеспокоены ограничениями памяти.

y = {yc{:}};

Когда выравнивание нагрузки, тот же процесс происходит, но, вместо каждого набора данных, имеющего то же количество отсчетов (1000 в предыдущем примере), количества отсчетов могут быть настроены, чтобы лучше всего использовать в своих интересах память и различия в скорости хостов - компьютеров рабочего.

Не требуется, что у каждого рабочего есть данные. Если элемент i из Составного значения не определено, рабочий i не будет использоваться в расчете.

Одно вычисление графического процессора

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

Для последних требований графического процессора смотрите веб-страницу для Parallel Computing Toolbox; или запросите MATLAB, чтобы определить, имеет ли ваш PC поддерживаемый графический процессор. Эта функция возвращает количество графических процессоров в вашей системе:

count = gpuDeviceCount
count =

    1

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

gpu1 = gpuDevice(1)
gpu1 = 

  CUDADevice with properties:

                      Name: 'GeForce GTX 470'
                     Index: 1
         ComputeCapability: '2.0'
            SupportsDouble: 1
             DriverVersion: 4.1000
        MaxThreadsPerBlock: 1024
          MaxShmemPerBlock: 49152
        MaxThreadBlockSize: [1024 1024 64]
               MaxGridSize: [65535 65535 1]
                 SIMDWidth: 32
               TotalMemory: 1.3422e+09
           AvailableMemory: 1.1056e+09
       MultiprocessorCount: 14
              ClockRateKHz: 1215000
               ComputeMode: 'Default'
      GPUOverlapsTransfers: 1
    KernelExecutionTimeout: 1
          CanMapHostMemory: 1
           DeviceSupported: 1
            DeviceSelected: 1

Самый простой способ использовать в своих интересах графический процессор состоит в том, чтобы задать вызов train и sim с аргументом 'useGPU' параметра установите на 'yes' ('no' значение по умолчанию).

net2 = train(net1,x,t,'useGPU','yes')
y = net2(x,'useGPU','yes')

Если net1 имеет учебную функцию по умолчанию trainlm, вы видите предупреждение, что вычисления графического процессора не поддерживают якобиевское обучение, только обучение градиента. Таким образом, учебная функция автоматически изменяется на функцию обучения градиента trainscg. Чтобы избежать уведомления, можно задать функцию перед обучением:

net1.trainFcn = 'trainscg';

Чтобы проверить, что обучение и симуляция происходят на устройстве графического процессора, запросите, чтобы ресурсы компьютера показали:

net2 = train(net1,x,t,'useGPU','yes','showResources','yes')
y = net2(x,'useGPU','yes','showResources','yes')

Каждая из вышеупомянутых линий кода выводит следующие сводные данные ресурсов:

Computing Resources:
GPU device #1, GeForce GTX 470

Много функций MATLAB автоматически выполняются на графическом процессоре, когда любой из входных параметров является gpuArray. Обычно вы перемещаете массивы в и от графического процессора с функциями gpuArray и gather. Однако для вычислений нейронной сети на графическом процессоре, чтобы быть эффективными, матрицы должны быть транспонированы, и столбцы дополнены так, чтобы первый элемент в каждом столбце выровнялся правильно в памяти графического процессора. Deep Learning Toolbox обеспечивает специальную вызванную функцию nndata2gpu перемещать массив в графический процессор и правильно организовывать его:

xg = nndata2gpu(x);
tg = nndata2gpu(t);

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

Перед обучением с gpuArray данными вход сети и выходные параметры должны быть вручную сконфигурированы с обычными матрицами MATLAB с помощью configure функция:

net2 = configure(net1,x,t);  % Configure with MATLAB arrays
net2 = train(net2,xg,tg);    % Execute on GPU with NNET formatted gpuArrays
yg = net2(xg);               % Execute on GPU
y = gpu2nndata(yg);          % Transfer array to local workspace

На графических процессорах и другом оборудовании, где вы можете хотеть развернуть свои нейронные сети, часто имеет место что показательная функция exp не реализован с оборудованием, но с библиотекой программного обеспечения. Это может замедлить нейронные сети, которые используют tansig сигмоидальная передаточная функция. Альтернативной функцией является Эллиот сигмоидальная функция, выражение которой не включает вызов никаких функций высшего порядка:

(equation)	a = n / (1 + abs(n))

Перед обучением, сеть tansig слои могут быть преобразованы в elliotsig слои можно следующим образом:

for i=1:net.numLayers
  if strcmp(net.layers{i}.transferFcn,'tansig')
    net.layers{i}.transferFcn = 'elliotsig';
  end
end

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

Распределенное вычисление графического процессора

Распределенный и вычисление графического процессора может быть объединен, чтобы выполнить вычисления через несколько центральных процессоров и/или графических процессоров на одиночном компьютере, или в кластере с MATLAB Parallel Server.

Самый простой способ сделать это должно задать train и sim для этого с помощью параллельного пула, определенного кластерным профилем, вы используете. 'showResources' опция особенно рекомендуется в этом случае, проверить, что ожидаемое оборудование используется:

net2 = train(net1,x,t,'useParallel','yes','useGPU','yes','showResources','yes')
y = net2(x,'useParallel','yes','useGPU','yes','showResources','yes')

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

net2 = train(net1,x,t,'useParallel','yes','useGPU','only','showResources','yes')
y = net2(x,'useParallel','yes','useGPU','only','showResources','yes')

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

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

numSamples = [1000 1000 1000 300];
xc = Composite;
tc = Composite;
for i=1:4
  xi = rand(2,numSamples(i));
  ti = xi(1,:).^2 + 3*xi(2,:);
  xc{i} = xi;
  tc{i} = ti;
end

Можно теперь задать это train и sim используйте эти три доступные графических процессора:

net2 = configure(net1,xc{1},tc{1});
net2 = train(net2,xc,tc,'useGPU','yes','showResources','yes');
yc = net2(xc,'showResources','yes');

Гарантировать, что графические процессоры привыкают первыми тремя рабочими, вручную преобразовывая Составные элементы каждого рабочего в gpuArrays. Каждый рабочий выполняет это преобразование в рамках параллельного выполнения spmd блок.

spmd
  if labindex <= 3
    xc = nndata2gpu(xc);
    tc = nndata2gpu(tc);
  end
end

Теперь данные задают, когда использовать графические процессоры, таким образом, вы не должны говорить train и sim сделать так.

net2 = configure(net1,xc{1},tc{1});
net2 = train(net2,xc,tc,'showResources','yes');
yc = net2(xc,'showResources','yes');

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

Параллельные временные ряды

Для сетей временных рядов просто используйте значения массива ячеек для x и t, и опционально включайте начальную входную задержку, утверждает xi и начальная задержка слоя утверждает ai, как требуется.

net2 = train(net1,x,t,xi,ai,'useGPU','yes')
y = net2(x,xi,ai,'useParallel','yes','useGPU','yes')

net2 = train(net1,x,t,xi,ai,'useParallel','yes')
y = net2(x,xi,ai,'useParallel','yes','useGPU','only')

net2 = train(net1,x,t,xi,ai,'useParallel','yes','useGPU','only')
y = net2(x,xi,ai,'useParallel','yes','useGPU','only')

Обратите внимание на то, что параллелизм происходит через выборки, или в случае временных рядов через различный ряд. Однако, если сеть только ввела задержки без задержек слоя, задержанные входные параметры могут быть предварительно вычислены так, чтобы в целях расчета, временные шаги стали различными выборками и могли быть параллелизированы. Дело обстоит так для сетей такой как timedelaynet и версии разомкнутого контура narxnet и narnet. Если сеть имеет задержки слоя, то время не может быть “сглажено” в целях расчета, и таким образом, одни серийные данные не могут быть параллелизированы. Дело обстоит так для сетей такой как layrecnet и версии с обратной связью narxnet и narnet. Однако, если данные состоят из нескольких последовательностей, они могут быть параллелизированы через отдельные последовательности.

Параллельная доступность, нейтрализации и обратная связь

Как упомянуто ранее, можно запросить MATLAB, чтобы обнаружить текущие параллельные ресурсы, которые доступны.

Чтобы видеть то, что графические процессоры доступны на хосте - компьютере:

gpuCount = gpuDeviceCount
for i=1:gpuCount
  gpuDevice(i)
end

Чтобы видеть, как многие рабочие запускаются в текущем параллельном пуле:

poolSize = pool.NumWorkers

Видеть графические процессоры, доступные через параллельный пул, работающий на кластере PC использование MATLAB Parallel Server:

spmd
  worker.index = labindex;
  worker.name = system('hostname');
  worker.gpuCount = gpuDeviceCount;
  try
    worker.gpuInfo = gpuDevice;
  catch
    worker.gpuInfo = [];
  end
  worker
end

Когда 'useParallel' или 'useGPU' установлены в 'yes', но параллель или рабочие графического процессора недоступны, соглашение состоит в том, что, когда ресурсы требуют, они используются при наличии. Расчет выполняется без ошибки, даже если они не. Этот процесс отступания от требуемых ресурсов до фактических ресурсов происходит можно следующим образом:

  • Если 'useParallel' 'yes' но Parallel Computing Toolbox недоступен, или параллельный пул не открыт, затем расчет возвращается к однопоточному MATLAB.

  • Если 'useGPU' 'yes' но gpuDevice для текущего сеанса работы с MATLAB является неприсвоенным или не поддержан, затем расчет возвращается к центральному процессору.

  • Если 'useParallel' и 'useGPU' 'yes', затем каждый рабочий с помощью уникального графического процессора использует тот графический процессор, и другие рабочие возвращаются к центральному процессору.

  • Если 'useParallel' 'yes' и 'useGPU' 'only', затем рабочие с помощью уникальных графических процессоров используются. Другие рабочие не используются, если ни у каких рабочих нет графических процессоров. В случае ни с какими графическими процессорами все рабочие используют центральные процессоры.

Когда не уверенный в том, какое оборудование на самом деле используется, проверяйте gpuDeviceCount, gpuDevice, и pool.NumWorkers гарантировать желаемое оборудование доступно, и вызов train и sim с 'showResources' установите на 'yes' проверять, какие ресурсы на самом деле использовались.