Lapack: Persyaratan prosesor untuk LAPACK

Dibuat pada 4 Jun 2021  ·  16Komentar  ·  Sumber: Reference-LAPACK/lapack

Kami sedang mengerjakan terjemahan LAPACK ke .NET. Kami menulis kompiler FORTRAN yang berhasil menerjemahkan semua LAPACK, termasuk semua pengujian. Pada tipe data nyata (hampir) semua tes lulus. Pada data yang kompleks, kami masih melihat beberapa masalah presisi.

Contoh:
XEIGTSTZ < zec.in - gagal karena underflow di ZLAHQR.
Langkah-langkah untuk mereproduksi: ZGET37 -> knt == 31, ZHSEQR -> ZLAHQR -> di akhir langkah QR kedua (ITS == 2) kode berikut menyebabkan underflow (pada register tertentu, lihat di bawah)

TEMP = H( I, I-1 )
    IF( DIMAG( TEMP ).NE.RZERO ) THEN
        RTEMP = ABS( TEMP)    ! <-- underflow on TEMP = (~1e-0173, ~1e-0173)
        IF (RTEMP .EQ. RZERO) RTEMP = CABS1(TEMP)
        H( I, I-1 ) = RTEMP
        TEMP = TEMP / RTEMP
        IF( I2.GT.I )

Kompiler kami menargetkan .NET CLR. JIT-nya memutuskan untuk menggunakan register SSE untuk ABS(TEMP), yang mengarah ke underflow dalam perhitungan menengah besarnya. Iffort (sebagai contoh lain) menggunakan register floating point dalam situasi ini, karenanya tidak underflow (karena panjangnya yang lebih besar: 80 bit). Saya mencoba untuk mendapatkan gambaran yang jelas (er) tentang apa yang diharapkan dari LAPACK mengenai rentang presisi/angka mana yang diperlukan dari kompiler/prosesor saat runtime.

Apakah semua tes untuk presisi ganda dirancang untuk memerlukan setidaknya 64 bit register? Atau apakah mereka dirancang sedemikian rupa agar berhasil untuk kumpulan kompiler FORTRAN populer yang tersedia saat ini? (Dalam kasus pertama, masalah di atas (dan masalah serupa lainnya) mungkin memerlukan perhatian. Haruskah saya mengajukan masalah untuk mereka?)

Saya mencari beberapa spesifikasi tetapi belum dapat menemukannya. Tautan apa pun juga akan dihargai. Terima kasih sebelumnya!

Question

Semua 16 komentar

Underflow itu sendiri bukanlah masalah yang sebenarnya. Setelah underflow, algoritme beralih ke CABS1, yang kurang rentan terhadap underflow. Masalah yang timbul adalah bahwa TEMP tidak akan benar-benar satu kesatuan, yang mengarah ke pembulatan di Z.

Solusi yang mungkin adalah melakukan pra-skala menggunakan CABS1 dan kemudian memperbaikinya menggunakan ABS (karena penskalaan pertama, ABS seharusnya tidak lagi meluap). (Saya tidak mendapatkan arus bawah pada mesin saya, jadi saya tidak dapat mengujinya untuk Anda)

IF (RTEMP .EQ. RZERO) THEN
    RTEMP = CABS1(TEMP)
    H( I, I-1 ) = RTEMP
    TEMP = TEMP / RTEMP
    RTEMP = ABS( TEMP)
    H( I, I-1 ) = H( I, I-1 )*RTEMP
    TEMP = TEMP / RTEMP
END IF

Saya pikir tes ini pasti dirancang untuk berhasil untuk kumpulan kompiler FORTRAN yang populer, karena begitulah cara mereka dijalankan. Memprediksi under/overflow sangat sulit. Setidaknya dalam kasus saya, subrutin ini dirancang hanya dengan mengujinya (menggunakan kompiler populer) secara menyeluruh dan memperbaiki kelebihan/kekurangan yang kami temukan.

Terima kasih! Ini sangat membantu.
Kami telah mencoba memulihkan dari underflow menggunakan CABS1. Tapi usaha kami tidak berjalan cukup jauh. Saran Anda tampaknya jauh lebih baik. Menggunakan ...

*
*        Ensure that H(I,I-1) is real.
*
         TEMP = H( I, I-1 )
         IF( DIMAG( TEMP ).NE.RZERO ) THEN
            RTEMP = ABS( TEMP)
            IF (RTEMP .EQ. RZERO) THEN 
                RTEMP = CABS1(TEMP)
                H( I, I-1 ) = RTEMP
                TEMP = TEMP / RTEMP
                RTEMP = ABS( TEMP)
                H( I, I-1 ) = H( I, I-1 )*RTEMP
            ELSE 
                H( I, I-1 ) = RTEMP
            END IF
            TEMP = TEMP / RTEMP
            IF( I2.GT.I )
     $         CALL ZSCAL( I2-I, DCONJG( TEMP ), H( I, I+1 ), LDH )
            CALL ZSCAL( I-I1, TEMP, H( I1, I ), 1 )
            IF( WANTZ ) THEN
               CALL ZSCAL( NZ, TEMP, Z( ILOZ, I ), 1 )
            END IF
         END IF
*
  130 CONTINUE

... iterasi ini berhasil diselesaikan (bahkan ketika menggunakan register SSE untuk ABS()).

Saya pikir tes ini pasti dirancang untuk berhasil untuk kumpulan kompiler FORTRAN yang populer, karena begitulah cara mereka dijalankan. Memprediksi under/overflow sangat sulit. Setidaknya dalam kasus saya, subrutin ini dirancang hanya dengan mengujinya (menggunakan kompiler populer) secara menyeluruh dan memperbaiki kelebihan/kekurangan yang kami temukan.

Rangkaian tes sangat membantu! Perkiraan kasar saya adalah bahwa kurang dari 1% pengujian dipengaruhi oleh masalah luapan ini atau yang serupa (saat menggunakan kompiler kami). Membuat pengujian lebih kuat terhadap under-/overflow dapat membantu membawa LAPACK ke lebih banyak platform. Upaya kami (gagal) di atas hanyalah satu contoh, yang dengan jelas menunjukkan, bahwa kami hampir tidak dapat menemukan perbaikan di pihak kami. Sebelum membuka beberapa masalah terkait, saya ingin memulai diskusi, apakah ada minat dalam perjalanan seperti itu atau tidak dan pendekatan apa yang baik.

Terima kasih atas peningkatannya @hokb dan @thijssteel! Haruskah saya menulis PR dengan modifikasi atau Anda bersedia melakukannya, @hokb?

Mengingat pengalaman saya yang terbatas dengan proyek ini, saya akan menghargai usaha Anda dan kesempatan untuk mengambil PR Anda sebagai pedoman untuk pot. PR masa depan dari kami... (kalau boleh?)

Halo @hokb ,

Saya mencari beberapa spesifikasi tetapi belum dapat menemukannya. Tautan apa pun juga akan dihargai. Terima kasih sebelumnya!

Saya tidak yakin apa pun ditentukan di mana saja.

Kompiler kami menargetkan .NET CLR. JIT-nya memutuskan untuk menggunakan register SSE untuk ABS(TEMP), yang mengarah ke underflow dalam perhitungan menengah besarnya. Iffort (sebagai contoh lain) menggunakan register floating point dalam situasi ini, karenanya tidak underflow (karena panjangnya yang lebih besar: 80 bit). Saya mencoba untuk mendapatkan gambaran yang jelas (er) tentang apa yang diharapkan dari LAPACK mengenai rentang presisi/angka mana yang diperlukan dari kompiler/prosesor saat runtime.

Pernyataan berani: Jika semua perhitungan dilakukan menggunakan aritmatika IEEE 64-bit, maka LAPACK akan berfungsi.

LAPACK tidak mengharapkan register 80-bit untuk membantu perhitungannya setiap saat. Algoritme dirancang dengan mempertimbangkan aritmatika 64-bit. Sekarang, seperti yang disebutkan oleh @thijssteel , LAPACK diuji dengan berbagai kompiler/arsitektur, dan kompiler/arsitektur ini terkadang menggunakan register 80-bit, dan kami mungkin berpikir bahwa algoritme kami hanya membutuhkan 64-bit selama ini, tetapi sebenarnya tidak, dan mereka, pada dasarnya, memang membutuhkan 80-bit.

Kami belum melakukan sesuatu yang sistematis dalam perjalanan kami untuk mengejar masalah ini. Secara umum, kami cukup senang ketika algoritma lulus test suite, dan, jika ada bantuan dari register 80-bit, biarlah.

Apakah semua tes untuk presisi ganda dirancang untuk membutuhkan setidaknya 64 bit register? Atau apakah mereka dirancang sedemikian rupa agar berhasil untuk kumpulan kompiler FORTRAN populer yang tersedia saat ini? (Dalam kasus pertama, masalah di atas (dan masalah serupa lainnya) mungkin memerlukan perhatian. Haruskah saya mengajukan masalah untuk mereka?)

Perkiraan kasar saya adalah bahwa kurang dari 1% pengujian dipengaruhi oleh masalah luapan ini atau yang serupa (saat menggunakan kompiler kami).

Astaga. 1%? Itu adalah jumlah besar yang menakutkan.

Pengujian banyak menguji di sekitar wilayah underflow dan overflow sehingga dapat diharapkan bahwa pengujian lebih mungkin dalam hal memicu masalah ini daripada kode pengguna tetapi tetap saja.

Membuat pengujian lebih kuat terhadap under-/overflow dapat membantu membawa LAPACK ke lebih banyak platform.

Portabilitas ke lebih banyak platform memang merupakan salah satu minat. Ketertarikan lainnya adalah presisi yang diperluas dengan paket seperti GMP di mana, seperti yang saya pahami, presisi tetap selama perhitungan. (Jadi misalnya Anda berpikir 256-bit, dan tidak ada register 300-bit yang akan membantu Anda.)

Upaya kami (gagal) di atas hanyalah satu contoh, yang dengan jelas menunjukkan, bahwa kami hampir tidak dapat menemukan perbaikan di pihak kami. Sebelum membuka beberapa masalah terkait, saya ingin memulai diskusi, apakah ada minat dalam perjalanan seperti itu atau tidak dan pendekatan apa yang baik.

Ya. Kami tertarik. Padahal kita hanya bisa berbuat banyak. Dan kami memiliki banyak di piring kami. Jadi mungkin kita mengambil masalah ini satu per satu, dan kita melihat seberapa jauh kita melangkah.

Bagaimanapun, memposting masalah di GitHub selalu merupakan ide yang bagus. Ini memberikan kesadaran untuk masalah, dan membantu mengumpulkan bantuan, ide-ide untuk memperbaiki masalah.

Saya senang kita menempuh jalan ini, tetapi saya akan merekomendasikan untuk santai saja.

Mungkin, untuk gfortran, kita harus mengkompilasi dengan flag -mfpmath=sse -msse2 untuk tujuan pengujian. Saya pikir ini akan memaksa semua perhitungan dilakukan dengan aritmatika 64-bit. Saya tidak yakin, lho.

Mengingat pengalaman saya yang terbatas dengan proyek ini, saya akan menghargai usaha Anda dan kesempatan untuk mengambil PR Anda sebagai pedoman untuk pot. PR masa depan dari kami... (kalau boleh?)

Tentu! Silakan, lihat #577.

@weslleyspereira Luar biasa! Saya masih memeriksa, apakah ini berlaku untuk CLAHQR yang sama. Akan memposting hasil saya ASAP (besok)

Halo @langou !

Pernyataan berani: Jika semua perhitungan dilakukan menggunakan aritmatika IEEE 64-bit, maka LAPACK akan berfungsi.

Bagus! Saya kira, dengan 'bekerja' yang kami maksud: ketika diberi makan dengan data 'dalam kisaran tertentu' itu tidak akan meluap karena ukuran register yang diberikan?

LAPACK tidak mengharapkan register 80-bit untuk membantu perhitungannya setiap saat. Algoritme dirancang dengan mempertimbangkan aritmatika 64-bit. Sekarang, seperti yang disebutkan oleh @thijssteel , LAPACK diuji dengan berbagai kompiler/arsitektur, dan kompiler/arsitektur ini terkadang menggunakan register 80-bit, dan kami mungkin berpikir bahwa algoritme kami hanya membutuhkan 64-bit selama ini, tetapi sebenarnya tidak, dan mereka, pada dasarnya, memang membutuhkan 80-bit.

Kami belum melakukan sesuatu yang sistematis dalam perjalanan kami untuk mengejar masalah ini. Secara umum, kami cukup senang ketika algoritma lulus test suite, dan, jika ada bantuan dari register 80-bit, biarlah.

Kedengarannya sangat masuk akal!

Perkiraan kasar saya adalah bahwa kurang dari 1% pengujian dipengaruhi oleh masalah luapan ini atau yang serupa (saat menggunakan kompiler kami).

Astaga. 1%? Itu adalah jumlah besar yang menakutkan.

Yah, kemungkinan 'jauh lebih sedikit' dari itu;)

Portabilitas ke lebih banyak platform memang merupakan salah satu minat. Ketertarikan lainnya adalah presisi yang diperluas dengan paket seperti GMP di mana, seperti yang saya pahami, presisi tetap selama perhitungan. (Jadi misalnya Anda berpikir 256-bit, dan tidak ada register 300-bit yang akan membantu Anda.)

Kedengarannya menarik, tapi saya tidak bisa mengomentari ini, karena saya kurang pengalaman dengan upaya presisi tetap seperti itu.

Ya. Kami tertarik. Padahal kita hanya bisa berbuat banyak. Dan kami memiliki banyak di piring kami. Jadi mungkin kita mengambil masalah ini satu per satu, dan kita melihat seberapa jauh kita melangkah.

Saya masih tidak yakin apa pendekatan umum yang baik. Telanjang dengan saya, jika pemahaman saya terlalu naif. Tetapi bukankah over-/underflow selalu bergantung pada keduanya: input data dan algoritme? Jadi, alih-alih membanjiri kode dengan pengujian bersyarat baru dan kode baru untuk memulihkannya, kami malah dapat mengurangi 'rentang yang diizinkan' untuk data input? Saya tidak memiliki wawasan yang diperlukan tentang upaya yang diperlukan untuk kedua pendekatan tersebut. Jadi saya tidak bisa menilai apa yang lebih layak.

Bagaimanapun, memposting masalah di GitHub selalu merupakan ide yang bagus. Ini memberikan kesadaran untuk masalah, dan membantu mengumpulkan bantuan, ide-ide untuk memperbaiki masalah.

Bagus. Kami akan mengajukan masalah saat kami pergi. Saya mengerti bahwa akan menjadi tantangan untuk menghasilkan perbaikan tanpa dapat mereproduksi arus bawah. Jadi, informasi apa yang dapat kami berikan untuk memperjelas masalah ini? Apakah jalan menuju underflow beton membantu? Yaitu: memberikan jumlah iterasi, nilai lokal saat ini bersama dengan nama file, dll.?

Saya senang kita menempuh jalan ini, tetapi saya akan merekomendasikan untuk santai saja.

Hal yang sama di sini! :)

Salah satu hasil dari #577 adalah bahwa LAPACK bergantung pada kompiler FORTRAN untuk mengimplementasikan divisi kompleks dan ABS() yang cukup kuat (di bawah / melimpah). Saya ingin tahu apakah kita harus mulai memelihara dokumen, mengumpulkan persyaratan semacam itu dan yang serupa? Mereka akan sama pentingnya dan berguna bagi siapa saja yang ingin menggunakan LAPACK dengan kompiler lain / baru, untuk pembuat kompiler dan untuk mentransfer sebagian atau semua algoritma LAPACK ke bahasa lain?

Tentu! Akan lebih baik jika informasi ini didokumentasikan dengan baik.

Untuk memulainya, saya menghabiskan beberapa waktu untuk melacak (mungkin) semua divisi dalam file LAPACK/SRC/z*.f (COMPLEX*16 algoritma) dari formulir

 REAL / COMPLEX   or   COMPLEX / COMPLEX

Saya menemukan total 53 file. Lihat file terlampir: complexDivisionFound.code-search

  • Untuk itu, saya menggunakan ekspresi REGEX dalam Kode Visual Studio:

    \n .*/ ^0-9 (?!DBLE)(?!NYATA)(?!MIN)(?!MAX)[^0-9]

Mungkin, untuk gfortran, kita harus mengkompilasi dengan flag -mfpmath=sse -msse2 untuk tujuan pengujian. Saya pikir ini akan memaksa semua perhitungan dilakukan dengan aritmatika 64-bit. Saya tidak yakin, lho.

Ya, seharusnya saat menggunakan GCC tetapi flag ini juga harus disetel secara default pada x86-64. Kutipan dokumentasi di bawah ini adalah untuk GCC 11 tetapi versi GCC yang jauh lebih lama harus menunjukkan perilaku yang sama. Menggunakan Koleksi Kompilator GNU (GCC): Opsi 3.19.59 x86

sse

Gunakan instruksi floating-point skalar yang ada di set instruksi SSE. Set instruksi ini didukung oleh Pentium III dan chip yang lebih baru, dan di lini AMD oleh chip Athlon-4, Athlon XP dan Athlon MP. Versi sebelumnya dari set instruksi SSE hanya mendukung aritmatika presisi tunggal, sehingga aritmatika presisi ganda dan diperpanjang masih dilakukan menggunakan 387. Versi yang lebih baru, hanya ada dalam chip Pentium 4 dan AMD x86-64, mendukung aritmatika presisi ganda juga.

Untuk kompiler x86-32, Anda harus menggunakan sakelar -march=cpu-type , -msse atau -msse2 untuk mengaktifkan ekstensi SSE dan membuat opsi ini efektif. Untuk kompiler x86-64, ekstensi ini diaktifkan secara default.

Kode yang dihasilkan harus jauh lebih cepat di sebagian besar kasus dan menghindari masalah ketidakstabilan numerik dari kode 387, tetapi dapat merusak beberapa kode yang ada yang mengharapkan sementara menjadi 80 bit.

Ini adalah pilihan default untuk kompiler x86-64, target Darwin x86-32, dan pilihan default untuk target x86-32 dengan set instruksi SSE2 ketika -ffast-math diaktifkan.

Contoh:
XEIGTSTZ < zec.in - gagal karena underflow di ZLAHQR.
Langkah-langkah untuk mereproduksi: ZGET37 -> knt == 31, ZHSEQR -> ZLAHQR -> di akhir langkah QR kedua (ITS == 2) kode berikut menyebabkan underflow (pada register tertentu, lihat di bawah)

TEMP = H( I, I-1 )
    IF( DIMAG( TEMP ).NE.RZERO ) THEN
        RTEMP = ABS( TEMP)    ! <-- underflow on TEMP = (~1e-0173, ~1e-0173)
        IF (RTEMP .EQ. RZERO) RTEMP = CABS1(TEMP)
        H( I, I-1 ) = RTEMP
        TEMP = TEMP / RTEMP
        IF( I2.GT.I )

Kompiler kami menargetkan .NET CLR. JIT-nya memutuskan untuk menggunakan register SSE untuk ABS(TEMP), yang mengarah ke underflow dalam perhitungan menengah besarnya. Iffort (sebagai contoh lain) menggunakan register floating point dalam situasi ini, karenanya tidak underflow (karena panjangnya yang lebih besar: 80 bit). Saya mencoba untuk mendapatkan gambaran yang jelas (er) tentang apa yang diharapkan dari LAPACK mengenai rentang presisi/angka mana yang diperlukan dari kompiler/prosesor saat runtime.

Untuk rekap:

  • Anda mengubah setengah juta baris Fortran77 menjadi C#.
  • Pengujian kode transpiled gagal saat menggunakan .NET just-in-time compiler.
  • Pengujian kode vanilla LAPACK berhasil saat menggunakan kompiler Intel Fortran (ifort).
  • Perbedaan yang diamati antara kedua kasus adalah penggunaan intermediet 80-bit oleh iffort yang menghindari underflow.

Benar?

Secara default GCC hanya menghasilkan kode untuk register float 64-bit pada x86-64 dan pada mesin saya biasanya semua tes LAPACK lulus kecuali untuk satu atau dua.

Apakah paket pengujian Netlib LAPACK lulus saat kompilasi dengan GCC?

edit: diselesaikan https://github.com/Reference-LAPACK/lapack/pull/577#issuecomment -859496175

Mungkin, untuk gfortran, kita harus mengkompilasi dengan flag -mfpmath=sse -msse2 untuk tujuan pengujian. Saya pikir ini akan memaksa semua perhitungan dilakukan dengan aritmatika 64-bit. Saya tidak yakin, lho.

saya mencoba -mfpmath=sse -msse2 dengan GCC 11 di MacOS dan Linux: https://github.com/weslleyspereira/lapack/actions/runs/966071530. Tidak ada kesalahan tambahan jika dibandingkan dengan alur kerja tanpa tanda tersebut: https://github.com/Reference-LAPACK/lapack/actions/runs/945060330 . Lihat #591

@hokb , dapatkah Anda mereproduksi masalah luapan yang Anda sebutkan di https://github.com/Reference-LAPACK/lapack/issues/575#issuecomment -855880000 dengan GCC menggunakan flag SSE? Bisakah Anda membantu saya dengan itu?

@weslleyspereira Saya bahkan belum mencoba GCC. Yang saya punya akses ke / setup yang sedang berjalan adalah ifort di Windows. Butuh beberapa hari bagi saya untuk mengaktifkan dan menjalankan GCC melalui cygwin untuk menguji (terutama dari kamar hotel liburan saya saat ini ... :| ) Beri tahu saya jika Anda membutuhkan saya untuk mengambil tantangan ini!
Setidaknya dan menurut https://godbolt.org/z/YYv5oPxe9 menggunakan flag tidak mempengaruhi kode yang dihasilkan oleh gfortran. Tapi tentu saja hanya uji coba yang akan memberi tahu pasti ...

Saya tidak menggunakan windows, tetapi saya memilikinya di sini. Saya akan mulai dengan menguji LAPACK dengan ift di Ubuntu saya dan melihat apa yang terjadi. Nikmati liburan!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat