Zainspirowany przez przekonujący wykład Herb Sutter'a Not your father's C++, Postanowiłem spojrzeć jeszcze raz na najnowszą wersję C++ przy użyciu Visual Studio 2010 Microsoftu. Szczególnie interesowało mnie twierdzenie Herba, że C++ jest "bezpieczny i szybki", ponieważ napisz dużo kodu krytycznego pod względem wydajności.Bezpiecznie i szybko FFT
Jako benchmark postanowiłem spróbować napisać ten sam prosty algorytm FFT w różnych językach.
wpadłem na następujący kod C++ 11, który wykorzystuje wbudowany w complex
rodzaju i vector
kolekcji:
#include <complex>
#include <vector>
using namespace std;
// Must provide type or MSVC++ barfs with "ambiguous call to overloaded function"
double pi = 4 * atan(1.0);
void fft(int sign, vector<complex<double>> &zs) {
unsigned int j=0;
// Warning about signed vs unsigned comparison
for(unsigned int i=0; i<zs.size()-1; ++i) {
if (i < j) {
auto t = zs.at(i);
zs.at(i) = zs.at(j);
zs.at(j) = t;
}
int m=zs.size()/2;
j^=m;
while ((j & m) == 0) { m/=2; j^=m; }
}
for(unsigned int j=1; j<zs.size(); j*=2)
for(unsigned int m=0; m<j; ++m) {
auto t = pi * sign * m/j;
auto w = complex<double>(cos(t), sin(t));
for(unsigned int i = m; i<zs.size(); i+=2*j) {
complex<double> zi = zs.at(i), t = w * zs.at(i + j);
zs.at(i) = zi + t;
zs.at(i + j) = zi - t;
}
}
}
Należy pamiętać, że funkcja ta działa tylko dla n
-elementowe wektorami gdzie n
jest integralną moc dwóch. Każdy, kto szuka szybkiego kodu FFT, który działa dla każdego n
powinien wyglądać na FFTW.
Jak rozumiem, tradycyjna składnia xs[i]
z C dla indeksowania vector
nie sprawdza granic, a zatem nie jest bezpieczna w pamięci i może być źródłem błędów pamięci, takich jak niedeterministyczna korupcja i naruszenia praw dostępu do pamięci . Więc zamiast tego użyłem xs.at(i)
.
Teraz chcę, aby ten kod był "bezpieczny i szybki", ale nie jestem ekspertem C++ 11, więc chciałbym poprosić o ulepszenia tego kodu, które uczyniłyby go bardziej idiotycznym lub wydajnym?
* "Chciałbym poprosić o ulepszenia tego kodu, które uczyniłyby go bardziej idiomatycznym lub wydajnym?" * - może [codereview] (http://codereview.stackexchange.com) byłoby lepszym miejscem do zapytania do recenzji. – Flexo
Większość, jeśli nie wszystkie, standardowe biblioteki oferują debugowanie iteratora/indeksu w trybie niezoptymalizowanym/debugowania, który sprawdza granice za pomocą 'operator []'. W trybie zwolnienia są wyłączone, dzięki czemu uzyskujesz pełną wydajność. FWIW, biblioteka MSVC jest jedną z nich. A jeśli nie jesteś pewien, czy robi to inna biblioteka, możesz po prostu napisać funkcję pomocnika, która wywołuje 'at' w debugowaniu i' operator [] 'w trybie zwolnienia. – Xeo
Z jakich innych języków korzystałeś? Byłoby interesujące zobaczyć porównanie. –