Saya memiliki daftar angka positif floating point yang cukup panjang ( std::vector<float>
, ukuran ~ 1000). Angka-angka diurutkan dalam mengurangi pemesanan. Jika saya menjumlahkan mereka mengikuti pesanan:
for (auto v : vec) { sum += v; }
Saya kira saya dapat memiliki beberapa masalah stabilitas numerik, karena mendekati akhir vektor sum
akan jauh lebih besar daripada v
. Solusi termudah adalah dengan melintasi vektor dalam urutan terbalik. Pertanyaan saya adalah: apakah itu efisien serta kasus maju? Saya akan memiliki lebih banyak cache yang hilang?
Apakah ada solusi pintar lainnya?
c++
floating-point
precision
Ruggero Turra
sumber
sumber
Jawaban:
Jadi tes untuk itu. Saat ini Anda memiliki masalah hipotetis, yaitu, tidak ada masalah sama sekali.
Jika Anda menguji, dan hipotetis terwujud menjadi masalah aktual , maka Anda harus khawatir benar-benar memperbaikinya.
Yaitu - presisi floating-point dapat menyebabkan masalah, tetapi Anda dapat mengonfirmasi apakah itu benar-benar cocok untuk data Anda, sebelum memprioritaskan hal itu di atas segalanya.
Seribu pelampung adalah 4Kb - itu akan masuk dalam cache pada sistem pasar massal modern (jika Anda memiliki platform lain dalam pikiran, beri tahu kami apa itu).
Satu-satunya risiko adalah bahwa prefetcher tidak akan membantu Anda saat iterasi mundur, tetapi tentu saja vektor Anda mungkin sudah ada dalam cache. Anda tidak dapat benar-benar menentukan ini sampai profil Anda dalam konteks program lengkap Anda, jadi tidak ada gunanya mengkhawatirkannya sampai Anda memiliki program lengkap.
Jangan khawatir tentang hal-hal yang mungkin menjadi masalah, sampai mereka benar-benar menjadi masalah. Paling-paling ada baiknya diperhatikan kemungkinan masalah, dan penataan kode Anda sehingga Anda dapat mengganti solusi yang paling sederhana dengan yang dioptimalkan dengan hati-hati nanti, tanpa menulis ulang yang lainnya.
sumber
Saya menandai penggunaan case Anda dan hasilnya (lihat gambar terlampir) menunjuk ke arah bahwa itu tidak membuat perbedaan kinerja untuk loop maju atau mundur.
Anda mungkin ingin mengukur pada kompiler perangkat keras + Anda juga.
Menggunakan STL untuk melakukan penjumlahan itu secepat pengulangan manual atas data tetapi jauh lebih ekspresif.
gunakan yang berikut ini untuk akumulasi terbalik:
sedangkan untuk akumulasi ke depan:
sumber
state
loop yang diberi batas waktu.Ya itu efisien. Prediksi cabang dan strategi cache cerdas dari perangkat keras Anda disesuaikan untuk akses berurutan. Anda dapat dengan aman mengumpulkan vektor Anda:
sumber
Untuk tujuan ini, Anda dapat menggunakan reverse iterator tanpa transposisi di
std::vector<float> vec
:Atau lakukan pekerjaan yang sama menggunakan algortitme standar:
Kinerja harus sama, hanya diubah arah memotong vektor Anda
sumber
Jika dengan stabilitas numerik yang Anda maksud adalah akurasi, maka ya, Anda mungkin berakhir dengan masalah akurasi. Bergantung pada rasio nilai terbesar ke nilai terkecil, dan persyaratan Anda untuk akurasi dalam hasil, ini mungkin atau mungkin tidak menjadi masalah.
Jika Anda ingin memiliki akurasi tinggi, maka pertimbangkan penjumlahan Kahan - ini menggunakan pelampung tambahan untuk kompensasi kesalahan. Ada juga penjumlahan berpasangan .
Untuk analisis terperinci tentang tradeoff antara akurasi dan waktu, lihat artikel ini .
PEMBARUAN untuk C ++ 17:
Beberapa jawaban lain menyebutkan
std::accumulate
. Sejak C ++ 17 ada kebijakan eksekusi yang memungkinkan algoritma diparalelkan.Contohnya
Ini harus membuat menjumlahkan dataset besar lebih cepat dengan biaya kesalahan pembulatan nondeterministik (saya berasumsi bahwa pengguna tidak akan dapat menentukan partisi thread).
sumber