Я работаю над реализацией MATLAB адаптивного умножения матрицы на вектор для очень больших разреженных матриц, полученных из конкретной дискретизации PDE (с известной структурой разреженности).
После долгой предварительной обработки я получаю несколько разных блоков (более, скажем, 200), для которых я хочу вычислить выбранные записи.
Одним из шагов предварительной обработки является определение (количества) записей в блоке, которое я хочу рассчитать, что дает мне почти идеальное измерение количества времени, которое займет каждый блок (во всех смыслах и целях квадратурное усилие — это одинаково для каждой записи).
Благодаря https://stackoverflow.com/a/9938666/2965879 я смог воспользоваться этим, заказав блоки в обратном порядке, что побуждает MATLAB начинать сначала с самых больших.
Однако количество записей настолько сильно отличается от блока к блоку, что прямой запуск parfor строго ограничивается блоками с наибольшим количеством записей, даже если они подаются в цикл в обратном порядке.
Мое решение состоит в том, чтобы делать самые большие блоки последовательно (но распараллеливать на уровне записей!), что нормально, если накладные расходы на итерацию не имеют большого значения, соответственно. блоки не становятся слишком маленькими. Остальные блоки я потом делаю парфором. В идеале я бы позволил MATLAB решить, как с этим справиться, но поскольку вложенный цикл parfor теряет свой параллелизм, это не работает. Кроме того, объединить обе петли в одну (почти) невозможно.
Теперь мой вопрос заключается в том, как лучше всего определить это отсечение между последовательным и параллельным режимом, принимая во внимание имеющуюся у меня информацию о количестве вхождений (форма кривой упорядоченных вхождений может различаться для разных задач), поскольку а также количество рабочих, которые у меня есть.
До сих пор я работал с 12 рабочими процессами, доступными по стандартной лицензии PCT, но с тех пор, как я начал работать с кластером, определение этого ограничения становится все более и более важным (поскольку для многих ядер накладные расходы последовательный цикл становится все более и более дорогостоящим по сравнению с параллельным циклом, но, аналогично, наличие блоков, удерживающих остальные, еще более дорогостоящим).
Для 12 ядер (соответственно конфигурации вычислительного сервера, с которым я работал) я нашел разумный параметр в 100 записей на одного рабочего в качестве ограничения, но это не работает, когда количество ядер не меньше по сравнению с количеством блоков (например, 64 против 200).
Я пытался уменьшить количество ядер с разной мощностью (например, 1/2, 3/4), но это также не всегда работает. Затем я попытался сгруппировать блоки в пакеты и определить отсечку, когда записи превышают среднее значение для пакета, соответственно. количество партий, в которых они находятся от конца:
logical_sml = true(1,num_core); i = 0;
while all(logical_sml)
i = i+1;
m = mean(num_entr_asc(1:min(i*num_core,end))); % "asc" ~ ascending order
logical_sml = num_entr_asc(i*num_core+(1:num_core)) < i^(3/4)*m;
% if the small blocks were parallelised perfectly, i.e. all
% cores take the same time, the time would be proportional to
% i*m. To try to discount the different sizes (and imperfect
% parallelisation), we only scale with a power of i less than
% one to not end up with a few blocks which hold up the rest
end
num_block_big = num_block - (i+1)*num_core + sum(~logical_sml);
(Примечание: этот код не работает для векторов num_entr_asc
, длина которых не кратна num_core
, но я решил опустить конструкции min(...,end)
для удобочитаемости.)
Я также опустил < max(...,...)
для объединения обоих условий (т. е. вместе с минимальным количеством записей на одного работника), что необходимо, чтобы отсечка не была обнаружена слишком рано. Я немного думал о том, чтобы как-то использовать и дисперсию, но пока все попытки были неудовлетворительны.
Я был бы очень признателен, если бы у кого-то была хорошая идея, как решить эту проблему.
Спасибо, что прочитали этот очень длинный вопрос,
С уважением,
Аксель
Пс. Поскольку мой «Уважаемый stackoverflow», кажется, отфильтрован, позвольте мне поблагодарить за то, что я уже много раз находил здесь решение своего вопроса.