Решите, когда использовать parfor

циклы parfor в MATLAB

parfor- цикл в MATLAB® выполняет серию операторов в теле цикла параллельно. Клиент MATLAB выпускает parfor команда и координаты с работниками MATLAB, чтобы выполнить итерации цикла параллельно на рабочих в параллельном пуле. Клиент отправляет необходимые данные по который parfor действует рабочим, где большая часть расчета выполняется. Результаты передают обратно клиенту и собирают.

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

Каждое выполнение тела parfor- циклом является iteration. Работники MATLAB оценивают итерации без определенного порядка и друг независимо от друга. Поскольку каждая итерация независима, нет никакой гарантии, что итерации синхронизируются в любом случае, и при этом нет никакой потребности в этом. Если количество рабочих равно количеству итераций цикла, каждый рабочий выполняет одну итерацию цикла. Если существует больше итераций, чем рабочие, некоторые рабочие выполняют больше чем одну итерацию цикла; в этом случае рабочий может получить несколько итераций целиком, чтобы уменьшать коммуникационное время.

Решение, Когда Использовать parfor

parfor- цикл может быть полезным, если у вас есть медленный for- цикл. Рассмотрите parfor если вы имеете:

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

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

parfor- цикл не может быть полезным, если вы имеете:

  • Код, который векторизовал for- циклы. Обычно, если вы хотите заставить код запуститься быстрее, сначала попытайтесь векторизовать его. Для получения дополнительной информации, как сделать это, смотрите Векторизацию (MATLAB). Векторизация кода позволяет вам извлекать выгоду из встроенного параллелизма, обеспеченного многопоточной природой многих базовых библиотек MATLAB. Однако, если вы векторизовали код, и у вас есть доступ только к локальным рабочим, затем parfor- циклы могут запуститься медленнее, чем for- циклы. Не делайте devectorize кода, чтобы допускать parfor; в целом это решение не работает хорошо.

  • Итерации цикла, которые занимают короткое время, чтобы выполниться. В этом случае параллель наверху доминирует над вашим вычислением.

Вы не можете использовать parfor- цикл, когда итерация в вашем цикле зависит от результатов других итераций. Каждая итерация должна быть независима от всех других. Для справки, имеющей дело с независимыми циклами, смотрите Убедитесь, что Итерации цикла parfor Независимы. Исключение к этому правилу должно накопить значения в цикле с помощью Переменных Сокращения.

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

  • for- циклы с в вычислительном отношении требовательной задачей. Эти циклы являются обычно хорошими кандидатами на преобразование в parfor- цикл, потому что время, необходимое для расчета, доминирует над временем, требуемым для передачи данных.

  • for- циклы с простой вычислительной задачей. Эти циклы обычно не извлекают выгоду из преобразования в parfor- цикл, потому что время, необходимое для передачи данных, является значительным по сравнению со временем, необходимым для расчета.

Пример parfor С низкой параллелью наверху

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

Этот пример вычисляет спектральный радиус матрицы и преобразует for- цикл в parfor- цикл. Узнайте, как измерить получившееся ускорение и сколько данных передается и от рабочих в параллельном пуле.

  1. В редакторе MATLAB введите следующий for- цикл. Добавьте tic и toc измерять время вычисления.

    tic
    n = 200;
    A = 500;
    a = zeros(n);
    for i = 1:n
        a(i) = max(abs(eig(rand(A))));
    end
    toc
  2. Запустите скрипт и отметьте прошедшее время.

    Elapsed time is 31.935373 seconds.

  3. В скрипте замените for- цикл с parfor- цикл. Добавьте ticBytes и tocBytes измеряться, сколько данных передается и от рабочих в параллельном пуле.

    tic
    ticBytes(gcp);
    n = 200;
    A = 500;
    a = zeros(n);
    parfor i = 1:n
        a(i) = max(abs(eig(rand(A))));
    end
    tocBytes(gcp)
    toc

  4. Запустите новый скрипт на четырех рабочих и запустите его снова. Обратите внимание на то, что первый показ медленнее, чем второй запуск, потому что параллельный пул занимает время, чтобы запустить и сделать код доступным для рабочих. Отметьте передачу данных и прошедшее время для второго запуска.

    По умолчанию MATLAB автоматически открывает параллельный пул рабочих на вашей локальной машине.

    Starting parallel pool (parpool) using the 'local' profile ... connected to 4 workers.
    ...
                 BytesSentToWorkers    BytesReceivedFromWorkers
                 __________________    ________________________
    
        1        15340                  7024                   
        2        13328                  5712                   
        3        13328                  5704                   
        4        13328                  5728                   
        Total    55324                 24168                   
    
    Elapsed time is 10.760068 seconds. 
    parfor работайте на четырех рабочих, приблизительно в три раза быстрее, чем соответствующий for- вычисление цикла. Ускорение меньше, чем идеальное ускорение фактора четыре на четырех рабочих. Это должно быть параллельным наверху, включая время, требуемое передавать данные от клиента рабочим и назад. Используйте ticBytes и tocBytes результаты исследовать переданный объем данных. Примите, что время, требуемое для передачи данных, пропорционально размеру данных. Это приближение позволяет вам получать индикацию времени, требуемого для передачи данных и сравнивать вашу параллель наверху с другим parfor- итерации цикла. В этом примере передача данных и параллель наверху малы по сравнению со следующим примером.

Текущий пример имеет низкую параллель наверху и извлекает выгоду из преобразования в parfor- цикл. Сравните этот пример с итерацией простого цикла в следующем примере, смотрите Пример parfor С Высокой Параллелью Наверху.

Для другого примера parfor- цикл с в вычислительном отношении требовательными задачами, смотрите Вложенный parfor и циклы for и Другие parfor Требования

Пример parfor С высокой параллелью наверху

В этом примере вы пишете цикл, чтобы создать простую синусоиду. Заменяя for- цикл с parfor- цикл не ускоряет ваше вычисление. Этот цикл не имеет большого количества итераций, не занимает много времени выполняться, и вы не замечаете увеличение скорости выполнения. Этот пример имеет высокую параллель наверху и не извлекает выгоду из преобразования в parfor- цикл.

  1. Запишите цикл, чтобы создать синусоиду. Используйте tic и toc измерять время протекло.

    tic
    n = 1024;
    A = zeros(n);
    for i = 1:n
        A(i,:) = (1:n) .* sin(i*2*pi/1024);
    end
    toc
    
    Elapsed time is 0.012501 seconds.
  2. Замените for- цикл с parfor- цикл. Добавьте ticBytes и tocBytes измеряться, сколько данных передается и от рабочих в параллельном пуле.

    tic
    ticBytes(gcp);
    n = 1024;
    A = zeros(n);
    parfor (i = 1:n)
        A(i,:) = (1:n) .* sin(i*2*pi/1024);
    end
    tocBytes(gcp)
    toc
    

  3. Запустите скрипт на четырех рабочих и запустите код снова. Обратите внимание на то, что первый показ медленнее, чем второй запуск, потому что параллельный пул занимает время, чтобы запустить и сделать код доступным для рабочих. Отметьте передачу данных и прошедшее время для второго запуска.

                 BytesSentToWorkers    BytesReceivedFromWorkers
                 __________________    ________________________
    
        1        13176                 2.0615e+06              
        2        15188                 2.0874e+06              
        3        13176                 2.4056e+06              
        4        13176                 1.8567e+06              
        Total    54716                 8.4112e+06              
    
    Elapsed time is 0.743855 seconds.
    Обратите внимание на то, что прошедшее время намного меньше для последовательного for- цикл, чем для parfor- цикл на четырех рабочих. В этом случае вы не извлекаете выгоду из превращения вашего for- цикл в parfor- цикл. Причина состоит в том, что передача данных очень больше в предыдущем примере, смотрите Пример parfor С Низкой Параллелью Наверху. В текущем примере параллель наверху доминирует над вычислительным временем. Поэтому итерация синусоиды не извлекает выгоду из преобразования в parfor- цикл.

Этот пример иллюстрирует, почему высокие параллельные служебные вычисления не извлекают выгоду из преобразования в parfor- цикл. Чтобы узнать больше об ускорении вашего кода, смотрите, Преобразуют циклы for В циклы parfor

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

| |

Похожие темы