Как правильно хранить переменные для использования с parfor? - PullRequest
3 голосов
/ 24 января 2020

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

Для этого я использую массивы ячеек со следующим синтаксисом: Assembly_ij = Tree{ithBranch}{jthAssembly}, где Assembly - матрица 18x3 double. Этот подход разрешен Matlab, однако, он совсем не улучшает выполнение кода. Я полагаю, что это связано с неправильным способом передачи переменных работникам. Я получаю следующее предупреждение:

Весь массив или структура «Дерево» является широковещательной переменной. Это может привести к ненужным коммуникационным издержкам.

Большая часть работы выполняется в этой части кода, и она должна передать ошибку, которую я делаю.

initialBranch = initialize();
Tree{1} = initialBranch;
for i = 2 : Nbranches
    branch = cell(1, elmsInBranch(i));
    parfor j = 1 : elmsInBranch(i)
        branch{j} = assembleBlocks(Tree{i-1}{2*j-1}, Tree{i-1}{2*j});
    end
    Tree{i} = branch;
end 

Matlab обязательно должен пройти целая древовидная структура для каждого работника, что является множеством бесполезного копирования. Я понятия не имею, как переписать его, чтобы он работал должным образом, однако, возможно, есть какой-нибудь умный способ извлечь только необходимые переменные для каждого работника ?

1 Ответ

3 голосов
/ 24 января 2020

Проблема в том, что вы передаете всю переменную Tree{i-1} в каждую (параллельную) итерацию parfor l oop. Это связано с тем, что интерпретатор MATLAB недостаточно «умен», чтобы определить, какие части Tree{i-1} вам понадобятся, потому что вы динамически индексируете его с помощью вычислений, основанных на j.

. Переменная temp во внешнем l oop, которая может быть напрямую проиндексирована с помощью j во внутреннем l oop, должна разрешать это:

initialBranch = initialize();
Tree{1} = initialBranch;
for i = 2 : Nbranches
    N = elmsInBranch(i);
    branch = cell(1, N);
    % Pre-partition the data to send individual packets to each node 
    iTrees = arrayfun( @(j) Tree{i-1}([2*j-1,2*j]), 1:N, 'uni', 0 );
    % Parallel loop...
    parfor j = 1 : N
        jTrees = iTrees{j}; % direct indexing using 'j', no calculation      
        branch{j} = assembleBlocks(jTrees{1}, jTrees{2});
    end
    Tree{i} = branch;
end

Обратите внимание, что cellfun, который я добавил разделяет ваши данные так, чтобы каждый параллельный узел мог напрямую индексировать по одному элементу за раз, который содержит оба элемента Tree, требуемые в l oop. Это может вызвать дублирование в памяти, но меньшее дублирование, чем передача всего массива каждому узлу!

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