Быстрое приближение для sin/cos в MATLAB
Я пытаюсь создать быстрое приближение sin и cos в MATLAB, которое является узким местом в моей программе. Есть ли более быстрый метод, чем встроенная процедура?
Узкое место: на каждой итерации получайте углы из сложной разреженной матрицы A (50000 x 50000) и векторов b и c (50000 x 1), затем найдите
S=[sin(ang(diag(A)+b-c) cos(ang(diag(A)+b-c)];
Все входы в sin и cos близки к +pi/2 или -pi/2.
Я пробовал справочную таблицу (как предложено в разделе Создание синусоидальной таблицы в C++) и простой ряд Тейлора, но оба они медленнее:
Справочная таблица:
appr=[round(1:.001:2,3);sin(1:.001:2);cos(1:.001:2)];
ang=round(angle(diag(A))+b-c);
loc=ang;
for cntr=1:length(ang)
loc(cntr)=find(appr(1,:)==abs(ang(cntr)),1);
end
S=[appr(loc,2).*sign(ang) appr(loc,3)];
Ряд Тейлора (вращение квадранта необходимо, чтобы приблизить ang=pi/2 к нулю)
ang=angle(diag(A))+b-c;
[ang,ind]=min(abs([ang+pi/2; ang-pi/2])); conv=[1 -1];
S=[(ang-0.1667*ang.^3).*conv(ind)), (1-0.5*ang.^2+0.041666*ang.^4).*conv(ind))];
Среднее время на MATLAB 2016a, Windows 8.1, i7-4500U@1,86 ГГц: встроенная функция sin/cos: 1,5 с | Таблица соответствия: 1,8 с | Серия Тейлора: 1,7 сек.
1 ответ
Попытка оптимизировать sin() и cos() (которые уже оптимизированы для рукояти) не принесет вам много пользы. В любом случае в вашем выражении:
S = [sin(angle(diag(A) + b - c)), cos(angle(diag(A) + b - c))];
другие операции займут время, сравнимое с грехом и cos. Вы запустили профилировщик, разделив выражение на составляющие? Это должно дать вам представление о том, какова относительная стоимость sin() и cos ().
Например:
A = pi*rand(10^7,1);
B = pi*rand(10^7,1);
C = A + i*B; % i is sqrt(-1)
tic;
S = sin(A);
toc;
Прошедшее время составляет 0.129710 секунд.
tic;
S = sin(angle(C) + B - C);
toc;
Прошедшее время составляет 0,757102 секунды.
Время действительно доминирует просто перемещением матриц в и из памяти.
В зависимости от точного характера вашего кода, набор инструментов gpu может быть опцией.