Вы, вероятно, не можете сэкономить время, но вы можете использовать векторизацию, чтобы избавиться от цикла и максимально использовать низкоуровневый код и кэширование. То, будет ли это на самом деле быстрее, зависит от ваших размеров, поэтому вам нужно провести несколько временных тестов, чтобы понять, стоит ли это того:
% dummy data
n = 3;
X = rand(n);
Y = rand(n);
S = rand(n);
% vectorize
b2 = sum(reshape((permute(reshape(X, [n, 1, n]).*Y, [3,2,1]) - S).^2, 1, []));
% check
b - b2 % close to machine epsilon i.e. zero
В результате мы вставляем новое одноэлементное измерение в один из массивов, заканчивая массивом размером [n, 1, n]
против массива с [n, n]
, причем последнее неявно совпадает с [n, n, 1]
. Первый перекрывающийся индекс соответствует i
в вашем цикле, остальные два индекса соответствуют индексам матрицы диадического произведения, которое вы имеете для каждого i
. Затем мы переставляем индексы, чтобы поставить индекс «i
» последним, чтобы мы могли снова передать результат с S
(неявного) размера [n, n, 1]
. Затем мы имеем матрицу размером [n, n, n]
, где первые два индекса - это матричные индексы в вашем оригинале, а последний соответствует i
. Затем нам нужно просто взять квадрат и сложить каждое слагаемое (вместо того, чтобы суммировать дважды, я преобразовал массив в строку и суммировал один раз).
Небольшое изменение вышеуказанных транспонирований S
вместо 3d-массива, которое может быть быстрее (опять же, вы должны рассчитать время):
b3 = sum(reshape((reshape(X, [n, 1, n]).*Y - reshape(S.', [1, n, n])).^2, 1, []));
С точки зрения производительности, reshape
бесплатен (он только интерпретирует данные, но не копирует), но permute
/ transpose часто приводит к попаданию перфорации при копировании данных.