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

циклы parfor в MATLAB

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

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

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

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

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

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

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

A parfor-цикл может не пригодиться, если у вас есть:

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

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

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

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

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

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

Пример parfor С низкими параллельными накладными расходами

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

Этот пример вычисляет спектральный радиус матрицы и преобразует for-цикл в a 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-цикл с a 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. 
    The parfor пробежать на четырех рабочих примерно в три раза быстрее, чем соответствующий for-цикл вычисление. Ускорение меньше, чем идеальное ускорение коэффициента четыре на четырех рабочих. Это связано с параллельными накладными расходами, включая время, необходимое для передачи данных от клиента работникам и обратно. Используйте ticBytes и tocBytes результаты для изучения объема переданных данных. Предположим, что время, необходимое для передачи данных, пропорционально размеру данных. Это приближение позволяет вам получить указание времени, необходимого для передачи данных, и сравнить ваши параллельные накладные расходы с другими parfor-итерации цикла. В этом примере передача данных и параллельные накладные расходы малы по сравнению со следующим примером.

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

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

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

В этом примере вы записываете цикл, чтобы создать простую синусоиду. Замена for-цикл с a 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-цикл с a 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-Loops в циклы parfor

См. также

| |

Похожие темы