Оптимизация кода, использующего repmat и bsxfun

Я написал ниже код для вычисления матрицы:

 vec0=repmat(vec,1,9);
 triw = (bsxfun(@times,vecO(1,:)',yc1)-bsxfun(@times,vecO(2,:)',xc1)).*(bsxfun(@times,vecO(2,:)',yc1)+bsxfun(@times,vecO(1,:)',xc1));

vec — это матрица 2×900, а xc1 и yc18100×900. Я использую этот код в цикле. Он очень медленный, поэтому я хотел бы улучшить его производительность. Как бы я это сделал?


person Oliver Range    schedule 20.09.2017    source источник
comment
Использование repmat с bsxfun, скорее всего, преступление!   -  person Divakar    schedule 20.09.2017
comment
.. если вы не занимаетесь ханкелингом/топлицированием/циркуляцией.   -  person Divakar    schedule 20.09.2017
comment
Что мне делать? @Divakar   -  person Oliver Range    schedule 20.09.2017
comment
Это был общий комментарий, не волнуйтесь об этом :)   -  person Divakar    schedule 20.09.2017
comment
Чтобы (слегка) ускорить его, избегая repmat, я полагаю, вы можете использовать reshape(yc1,900,[]) вместо yc1 и то же самое для xc1 во всех местах.   -  person    schedule 20.09.2017


Ответы (1)


Мне удалось ускорить работу примерно на 30-40%, реорганизовав вычисления в 2 вызова bsxfun вместо 4:

triw = bsxfun(@times, prod(vec0).', yc1.^2-xc1.^2)-...
       bsxfun(@times, diff(vec0.^2).', xc1.*yc1);

Обратите внимание, что я также использовал оператор транспонирования массива .' вместо комплексно-сопряженный оператор транспонирования '. Первый просто реорганизует массив без изменения значений, а второй может дать вам другие результаты, если вы имеете дело с сложные данные.

Вот код, который я использовал для сравнения двух подходов:

% Random test data:
vec0 = rand(2, 8100);
xc1 = rand(8100, 900);
yc1 = rand(8100, 900);

% Define anonymous functions to test:
fcn1 = @(v, x, y) (bsxfun(@times, v(1, :).', y)-bsxfun(@times, v(2, :).', x)).*...
                  (bsxfun(@times, v(2, :).', y)+bsxfun(@times, v(1, :).', x));
fcn2 = @(v, x, y) bsxfun(@times, prod(v).', y.^2-x.^2)-...
                  bsxfun(@times, diff(v.^2).', x.*y);

% Test the mathematical accuracy:
triw1 = fcn1(vec0, xc1, yc1);
triw2 = fcn2(vec0, xc1, yc1);
max(abs(triw1(:)-triw2(:)))

ans =
     4.440892098500626e-16

% Time the results:
t1 = timeit(@() fcn1(vec0, xc1, yc1))

t1 =
   0.107775908242267  % seconds

t2 = timeit(@() fcn2(vec0, xc1, yc1))

t2 =
   0.068403928901861  % seconds

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

person gnovice    schedule 20.09.2017