2013-12-10 1 views
1

Мне удалось получить помощь в векторизации этого цикла, но если я попытаюсь запустить его, когда array1/xfreq_orig имеет 500 000 строк или t_rebuilt имеет 500 000 Я запускаю из барана, который у меня есть 16gig.Ускорение цикла, поскольку у меня заканчивается память, когда я его векторика

array1=[xfreq_orig,yamp_orig,yamp_inv,phase_orig] %frequency, amplitudes, phases to use 
t_rebuilt=linspace(0,2*pi,44100) 


aa_sig_rebuilt_L=zeros(1,length(t_rebuilt)); 
aa_sig_combined_L=zeros(1,length(t_rebuilt)); 
sig_full_L=zeros(1,length(t_rebuilt)); 

for kk=1:1:numel(xfreq_orig); 

    aa_sig_rebuilt_L = array1(kk, 2)*cos ((array1(kk,1))*t_rebuilt+(array1(kk, 4))); 
    aa_sig_combined_L = aa_sig_combined_L + aa_sig_rebuilt_L; 

end 

sig_full_L=(aa_sig_combined_L/max(abs(aa_sig_combined_L))*.8); 

Вот vectorised версия, но я бегу из памяти, когда array1/xfreq_orig Роу велики, как 500000 или если t_rebuilt большой массив как t_rebuilt = LINSPACE (0,2 * пи, 544100)

a = array1; 
t = t_rebuilt; 

aa_sig_rebuilt_L = bsxfun(@times, a(:,2) , ... 
        cos(bsxfun(@plus, bsxfun(@times, a(:,1), t), a(:,4)))); 

aa_sig_combined_L = sum(aa_sig_rebuilt_L); 

Вот объяснение того, почему от Криса Тейлора ответа. «Имейте в виду, что это будет использовать больше памяти, чем версия будет циклом (она будет использовать numel (xfreq_orig) раз столько же памяти, сколько она вычисляет каждую строку aa_sig_rebuilt_L перед их суммированием, тогда как цикл вычисляет каждую строку, добавляет ее к сумма, а затем отбрасывает ее).

vectorizing a matlab/octave FOR loop

Кто-нибудь есть какие-либо предложения о том, как ускорить этот процесс для контура вверх, так как если я vectorise это я убегу из памяти? Есть еще один способ vectorise это, так что я не буду бежать из памяти при использовании большого количества строк для array1/xfreq_orig или t_rebuilt

ответ

2

Да, это тот случай, когда bsxfun (три раза!), Вероятно, не хорошая идея. Иногда паранойя людей о петлях в Матлабе заходит слишком далеко. Они отлично подходят, и если они используются в соответствующих ситуациях, во многих случаях они могут быть быстрее других вариантов (и имеют преимущество в том, что они очень читаемы). Обновление уравнений и рекуррентных отношений, подобных вашей системе, - это именно тот тип системы, который может быть лучше реализован с помощью цикла for. Если вы запустите цикл и код bsxfun для небольших входов, вы увидите, что они очень сопоставимы.

Вы делаете то, что похоже на много ненужного выделения в вашем коде. Например, aa_sig_rebuilt_L и sig_full_L не обязательно должны быть предварительно распределены. Они будут автоматически распределены при их инициализации. Вы также создали большой массив, array1, из меньших и выполняете двумерную индексацию на каждой итерации цикла for. Те будут очищать ваш код и, возможно, давать небольшие ускорения, но вы действительно получите наибольшее ускорение от избавления от временной переменной aa_sig_rebuilt_L и помещения всего на одну строку. Это не должно работать с компиляцией JIT, но иногда это происходит. Вот моя версия:

t_rebuilt = linspace(0,2*pi,544100); 
aa_sig_combined_L1 = zeros(1,length(t_rebuilt)); 
for i=1:length(xfreq_orig); 
    aa_sig_combined_L1 = aa_sig_combined_L1 + ... 
     yamp_orig(i)*cos(xfreq_orig(i)*t_rebuilt+phase_orig(i)); 
end 

Он по-прежнему занимает некоторое время, чтобы работать на моей машине, но вы не должны запустить из памяти, если другие части вашего кода не уже использовали его (проверить с whos). Если у вас заканчивается нехватка памяти, вы можете попробовать явно очистить большие неиспользуемые переменные с помощью clear (in Octave). Помимо этого вы можете изучить код, используя mex, или использовать codgen, чтобы автоматически выводить вашу функцию на код C, который вызывается из Matlab. В Октаве: Dynamically Linked Functions – Oct-Files and Mex-Files.

2

С одной стороны, вы хотели бы использовать векторизация Matlab, то есть используя все данные. С другой стороны, вы не можете этого сделать, потому что у вас недостаточно ОЗУ. Даже если у вас достаточно, выделение большого количества оперативной памяти приведет к замедлению вашего вычисления.

Одним из решений является разделение данных на части, загрузка соответствующей части с диска и выполнение на ней векторизованных вычислений. Вы можете немного поиграть с этим параметром, чтобы узнать, что дает лучшую производительность.

Смежные вопросы