J'espère que quelqu'un pourra revoir mon code ci-dessous et vous donner des conseils pour accélérer la section entre tic et toc. La fonction ci-dessous tente d'effectuer un IFFT plus rapidement que la fonction intégrée de Matlab puisque (1) presque tous les bots de coefficients fft sont nuls (c.-à-d. 10
à 1000
les bins sur 10M
à 300M
sont non nulles), et (2) seulement le tiers central des résultats de l'IFFT est conservé (le premier et le dernier tiers sont rejetés - donc pas besoin de les calculer en premier lieu).Accélérer les calculs FFT clairsemés
Les variables d'entrée sont les suivants:
fftcoef = complex fft-coef 1D array (10 to 1000 pts long)
bins = index of fft coefficients corresponding to fftcoef (10 to 1000 pts long)
DATAn = # of pts in data before zero padding and fft (in range of 10M to 260M)
FFTn = DATAn + # of pts used to zero pad before taking fft (in range of 16M to 268M) (e.g. FFTn = 2^nextpow2(DATAn))
Actuellement, ce code prend quelques ordres de grandeur plus que l'approche de la fonction de Matlab ifft
qui calcule l'ensemble du spectre élimine alors 2/3
« s de celui-ci. Par exemple, si les données d'entrée pour fftcoef et les bacs sont 9x1
tableaux (par exemple seulement 9
coefficients fft complexes par bande latérale, 18
pts lorsque l'on considère les deux bandes latérales), et DATAn=32781534
, FFTn=33554432
(c.-à-2^25
), l'approche IFFT prend 1.6
secondes alors que la boucle ci-dessous prend plus de 700
secondes.
J'ai évité d'utiliser une matrice pour vectoriser la boucle nn car parfois la taille du tableau pour fftcoef et bacs pourrait être jusqu'à 1000
pts long, et une matrice 260Mx1K
serait trop grand pour la mémoire à moins qu'il puisse être divisé en quelque sorte .
Un conseil est très apprécié! Merci d'avance.
function fn_fft_v1p0(fftcoef, bins, DATAn, FFTn)
fftcoef = [fftcoef; (conj(flipud(fftcoef)))]; % fft coefficients
bins = [bins; (FFTn - flipud(bins) +2)]; % corresponding fft indices for fftcoef array
ttrend = zeros((round(2*DATAn/3) - round(DATAn/3) + 1), 1); % preallocate
start = round(DATAn/3)-1;
tic;
for nn = start+1 : round(2*DATAn/3) % loop over desired time indices
% sum over all fft indices having non-zero coefficients
arg = 2*pi*(bins-1)*(nn-1)/FFTn;
ttrend(nn-start) = sum(fftcoef.*(cos(arg) + 1j*sin(arg));
end
toc;
end
Voir http://www.fftw.org/pruned.html pour une analyse des économies potentielles. Cela ne vaut peut-être pas la peine. – mtrw
Vous regardez les opérations 'length (bins) * (2 * DATAn/3)', mieux que 'DATAn * lg (DATAn)' pour l'approche FFT si '2 * length (bins)/3> lg (DAtan) '(puisque FFTW gère les tailles de transformation non-power-of-2, j'ignore le pad-zero). Pour le cas de 10 bins et de 2^25 points de sortie, c'est '20/3> 25 ', un facteur potentiel de 3 amélioration. Dès que vous arrivez à 75 coeffs FFT, vous avez perdu l'avantage. Et vous devez coder l'algorithme en C et le maintenir. – mtrw
Merci mtrw, j'ai passé en revue le lien ci-dessus il y a quelques jours. Il m'a initialement donné l'espoir, car il dit: "Pour cette raison, je ne recommanderais pas d'envisager une FFT 1d élaguée sauf si vous voulez 1% des sorties ou moins (et/ou si 1% ou moins de vos entrées sont non nulles) " Dans mon cas, moins de 0,00001% de mes entrées (coefficients à IDFT) sont non nulles. Je pense que cela devrait être la principale raison de l'augmentation de la vitesse, plutôt que le facteur de 3 amélioration que vous citez ci-dessus. – ggkmath