Bagaimana cara mengatasi non-associativity numerik untuk reduksi paralel?

17

Pengurangan paralel mengasumsikan bahwa operasi yang sesuai adalah asosiatif. Asumsi ini dilanggar karena penambahan angka floating point. Anda mungkin bertanya mengapa saya peduli tentang ini. Yah, itu membuat hasil yang kurang dapat direproduksi. Dan menjadi lebih buruk ketika anil simulasi digunakan untuk mengoptimalkan (atau menyesuaikan parameter) dibandingkan subrutin yang menghasilkan hasil yang tidak dapat direproduksi.

Apa cara umum untuk mengatasi masalah ini? Apa yang bisa dikatakan tentang strategi berikut?

  • Jangan pedulikan hal yang tidak dapat direproduksi.
  • Jangan gunakan reduksi paralel dengan angka floating point dan penambahan.
  • Buat paket kerja berukuran sesuai dengan cara yang dapat direproduksi, dan lakukan reduksi akhir dengan tangan.
  • Gunakan presisi yang lebih tinggi untuk penambahan (tetapi tidak semua kompiler menawarkan tipe floating point presisi yang lebih tinggi).
Thomas Klimpel
sumber
Apakah Anda khawatir tentang reproduktifitas pada jumlah proses yang sama atau reproduktifitas pada sejumlah prosesor yang berbeda? Berapa banyak hit kinerja yang bersedia Anda ambil untuk reproduktifitas bitwise? Apakah Anda hanya tertarik dengan anil simulasi?
Jed Brown
@JedBrown Saya khawatir tentang kemungkinan untuk mendapatkan hasil yang dapat direproduksi, misalnya untuk men-debug masalah potensial. Tidak masalah bagi saya jika ada cara untuk mereproduksi hasil, misalnya dengan menggunakan jumlah prosesor yang sama (atau dengan hanya "mengetahui" jumlah prosesor yang digunakan pada awalnya). Saya akan bersedia untuk mengambil hit kinerja terkait dengan menggunakan tipe floating point presisi yang lebih tinggi untuk penambahan itu sendiri. Masalah konkret saya sebagian besar terkait dengan perbedaan simulasi anil dan tak terduga, tetapi semua ini ternyata adalah bug nyata.
Thomas Klimpel

Jawaban:

15

Pengurangan yang diimplementasikan menggunakan MPI_Allreduce()direproduksi selama Anda menggunakan jumlah prosesor yang sama, asalkan implementasi mengamati catatan berikut ini muncul di Bagian 5.9.1 dari standar MPI-2.2.

Saran untuk pelaksana . Sangat disarankan MPI_REDUCEuntuk diimplementasikan sehingga hasil yang sama diperoleh setiap kali fungsi diterapkan pada argumen yang sama, muncul dalam urutan yang sama. Perhatikan bahwa ini dapat mencegah optimasi yang memanfaatkan lokasi fisik prosesor. ( Akhir saran untuk pelaksana .)

Jika Anda perlu menjamin reproduktifitas dengan cara apa pun, Anda dapat mengikuti panduan di paragraf berikut:

Nasihat untuk pengguna . Beberapa aplikasi mungkin tidak dapat mengabaikan sifat non-asosiatif dari operasi floating-point atau dapat menggunakan operasi yang ditentukan pengguna (lihat Bagian 5.9.5) yang memerlukan urutan pengurangan khusus dan tidak dapat diperlakukan sebagai asosiatif. Aplikasi semacam itu harus menegakkan urutan evaluasi secara eksplisit. Misalnya, dalam kasus operasi yang memerlukan urutan evaluasi dari kiri ke kanan (atau kanan ke kiri) yang ketat, ini dapat dilakukan dengan mengumpulkan semua operan dalam satu proses tunggal (misalnya, dengan MPI_GATHER), menerapkan operasi pengurangan dalam urutan yang diinginkan (misalnya, dengan MPI_REDUCE_LOCAL), dan jika perlu, menyiarkan atau menyebarkan hasilnya ke proses lain (misalnya, dengan MPI_BCAST). ( Akhir saran untuk pengguna .)

Dalam skema yang lebih luas, algoritma yang efisien untuk sebagian besar aplikasi memanfaatkan lokalitas. Karena algoritma ini benar-benar berbeda ketika dijalankan pada sejumlah proses yang berbeda, tidak praktis untuk mereproduksi hasil secara tepat ketika dijalankan pada sejumlah proses yang berbeda. Pengecualian yang mungkin adalah multigrid dengan Jacobi teredam atau polinomial (misalnya Chebyshev), di mana dimungkinkan untuk metode sederhana ini bekerja dengan sangat baik.

Dengan jumlah proses yang sama, seringkali bermanfaat bagi kinerja untuk memproses pesan dalam urutan yang diterima (misalnya menggunakan MPI_Waitany()), yang memperkenalkan non-determinisme. Dalam kasus seperti itu, Anda dapat mengimplementasikan dua varian, yang cepat yang menerima dalam urutan apa pun dan yang "men-debug" yang menerima dalam urutan statis. Ini mensyaratkan bahwa semua pustaka yang mendasarinya juga ditulis untuk menawarkan perilaku ini.

Untuk debugging dalam beberapa kasus, Anda dapat mengisolasi bagian dari perhitungan yang tidak menawarkan perilaku yang dapat direproduksi ini dan melakukan hal itu secara berlebihan. Tergantung pada bagaimana komponen dirancang, perubahan itu mungkin sejumlah kecil kode atau sangat mengganggu.

Jed Brown
sumber
6

Untuk sebagian besar saya mengirim jawaban Jed. Namun, ada jalan keluar yang berbeda: Mengingat ukuran angka floating point normal, Anda dapat menyimpan setiap angka dalam angka titik tetap bit 4000 atau lebih. Jadi, jika Anda melakukan pengurangan angka floating point yang tertanam, Anda mendapatkan perhitungan yang pasti, tidak peduli asosiatifitasnya. (Maaf, saya tidak punya referensi untuk yang datang dengan ide ini.)

Victor Eijkhout
sumber
1
Saya tidak berpikir dia adalah yang pertama, tetapi rekan Anda Dr. Bandwidth tentu saja memiliki artikel yang bagus tentang topik ini: sites.utexas.edu/jdm4372/2012/02/15/…
Jeff
5

Anda dapat menerapkan algoritme reduksi yang stabil secara numerik dalam MPI sama seperti yang Anda lakukan secara serial. Mungkin ada hit kinerja, tentu saja. Jika Anda mampu mereplikasi vektor, cukup gunakan MPI_Gather dan lakukan pengurangan serial secara stabil pada root. Dalam beberapa kasus, Anda mungkin menemukan performa yang baik bukan masalah besar.

Solusi lain adalah dengan menggunakan akumulator luas seperti yang dijelaskan di sini . Anda dapat melakukan ini dengan MPI sebagai pengurangan yang ditentukan pengguna, meskipun akan menggunakan bandwidth yang lebih banyak.

Kompromi untuk hal di atas adalah menggunakan penjumlahan terkompensasi. Lihat referensi "penjumlahan Kahan" untuk detailnya. “ Akurasi dan Stabilitas Algoritma Numerik ” Higham adalah sumber yang bagus untuk topik ini.

Jeff
sumber
2

Saya ingin menunjukkan bahwa alih-alih menggunakan aritmatika presisi lebih tinggi untuk penambahan, ada kemungkinan menggunakan penjumlahan terkompensasi (lihat [1]). Ini bisa meningkatkan akurasi penjumlahan tanpa perlu menggunakan tipe data yang lebih besar.

[1] Higham, NJ Akurasi Penjumlahan Floating Point. Jurnal SIAM pada Scientific Computing 14, 783-799 (1993).

Juan M. Bello-Rivas
sumber