Я пытаюсь распараллелить некоторый код, используемый в алгоритме Гаусса-Зейделя, для аппроксимации решения системы линейных уравнений.
Вкратце, для матрицы NxN
за одну итерацию я делаю sqrt(N)
сеанса параллельных вычислений, один за другим. За один сеанс параллельных вычислений я распределяю задачу вычисления sqrt(N)
значений из вектора между доступными воркерами.
Код, задействованный в сеансе параллельных вычислений, таков:
future_results(1:num_workers) = parallel.FevalFuture;
for i = 1:num_workers
start_itv = buck_bound+1 + (i - 1) * worker_length;
end_itv = min(buck_bound+1 + i * worker_length - 1, ends_of_buckets(current_bucket));
future_results(i) = parfeval(p, @hybrid_parallel_function, 3, A, b, x, x_last, buck_bound, n, start_itv, end_itv);
end
for i = 1:num_workers
[~, arr, start_itv, end_itv] = fetchNext(future_results(i));
x(start_itv:end_itv) = arr;
end
Функция, вызываемая parfeval
, такова:
function [x_par, start_itv, end_itv] = hybrid_parallel_function (A, b, x, x_last, buck_bound, n, start_itv, end_itv)
x_par = zeros(end_itv - start_itv + 1, 1);
for i = start_itv:end_itv
x_par(i-start_itv+1) = b(i);
x_par(i-start_itv+1) = x_par(i-start_itv+1) - A(i, 1:buck_bound) * x(1:buck_bound);
x_par(i-start_itv+1) = x_par(i-start_itv+1) - A(i, buck_bound+1:i-1) * x_last(buck_bound+1:i-1);
x_par(i-start_itv+1) = x_par(i-start_itv+1) - A(i, i+1:n) * x_last(i+1:n);
x_par(i-start_itv+1) = x_par(i-start_itv+1) / A(i, i);
end
end
Весь код можно найти здесь: https://pastebin.com/hRQ5Ugqz
Профилировщик Matlab для матрицы 1000x1000
. Параллельный код от 20 до 135 раз медленнее, чем его последовательный аналог, в зависимости от выбранной матрицы коэффициентов (и все еще намного быстрее, чем spmd
).
Вычисление парфеваля может быть лениво разделено между строками 50 и 57? Тем не менее, я не могу объяснить себе, почему существуют такие большие накладные расходы. Кажется, это как-то связано с тем, сколько раз вызывается парфеваль: я уменьшил время выполнения, уменьшив количество вызовов парфеваля.
Есть ли что-то, что можно еще оптимизировать? Должен ли я прибегать к написанию кода на C++?
Пожалуйста помоги. Большое спасибо!