Inferensi Jenis

StableHLO awalnya di-bootstrap dari dialek MHLO, dan mewarisi implementasi MHLO dari inferensi jenis. Kemajuan implementasi dilacak di status.md.

Panduan yang diusulkan di bawah ini dimaksudkan untuk memastikan penerapan pemverifikasi berkualitas tinggi dan fungsi bentuk untuk operasi StableHLO.

Proposal

Proposal ini berlaku untuk meninjau kembali implementasi yang ada dan mencapai operasi baru hingga cakupan komprehensif.

(P1) Menggunakan spesifikasi StableHLO sebagai sumber kebenaran

spec adalah sumber tepercaya untuk semua pemverifikasi dan fungsi bentuk operasi StableHLO. Pemverifikasi dan fungsi bentuk yang ada dari setiap operasi perlu ditinjau kembali agar sepenuhnya selaras dengan spesifikasi. Perlu diperhatikan bahwa dokumen spesifikasi terus berkembang. Jika spesifikasi untuk operasi tidak tersedia, implementasi XLA harus digunakan sebagai sumber kebenaran, termasuk xla/service/shape_inference.cc dan xla/service/hlo_verifier.cc. Implementasi XLA tidak mencakup dinamisme tak terbatas. Jadi, untuk dinamisme tanpa batas, kami akan menerapkan akal sehat sampai RFC dinamis tersedia.

(P2) Memaksimalkan ODS

File ODS (seperti StablehloOps.td) menentukan operasi dengan karakteristik dan jenis untuk setiap operand/atribut/hasil, dan akan melakukan verifikasi. Dengan demikian, TIDAK diperlukan kode verifikasi dalam pemverifikasi atau fungsi bentuk untuk properti yang sudah dijamin oleh ODS. Hapus kode verifikasi jika diduplikasi dengan ODS, karena kode tersebut tidak akan pernah dipicu.

Apakah kita perlu menambahkan pengujian untuk batasan dari ODS? Lihat Menetapkan pedoman pengujian.

(P3) Mempertahankan kode verifikasi pada pemverifikasi dan fungsi bentuk

Keduanya:

  • pemverifikasi: diterapkan oleh Op::verify(), dan
  • fungsi bentuk: diimplementasikan oleh InferTypeOpInterface seperti Op::inferReturnTypes() atau Op::inferReturnTypeComponents

mungkin memiliki kode verifikasi untuk memeriksa operand/atribut/hasil. Pemisahan awal mungkin adalah sebagai berikut: Biarkan pemverifikasi memeriksa operand/atribut, lalu biarkan fungsi bentuk hanya menghitung jenis hasil yang ditentukan dan memeriksa kompatibilitasnya terhadap jenis hasil yang sebenarnya. Namun, pada kenyataannya pembagian ini memiliki beberapa masalah:

  • Fungsi bentuk dapat dipanggil oleh fungsi build() yang dibuat secara otomatis, tanpa memanggil pemverifikasi terlebih dahulu. Jadi input terkait juga harus diverifikasi dalam fungsi bentuk.
  • Kode duplikat: Misalnya, dalam pemverifikasi, kami melakukan beberapa pemrosesan pada operand, lalu memverifikasi beberapa hasil perantara. Kemudian, hasil menengah ini berguna untuk menyimpulkan hasil akhir dalam fungsi bentuk. Hasil menengah ini harus dihitung dua kali.
  • Beban pemeliharaan: Verifikasi pengoperasian dilakukan dalam dua metode yang berbeda.

Solusinya adalah sebagai berikut:

  1. Untuk sebagian besar operasi tanpa region (seperti PadOp): Coba masukkan semua kode verifikasi ke dalam fungsi bentuk, dan hapus pemverifikasi sepenuhnya. Jika hal ini tidak memungkinkan karena tidak dapat menyimpulkan jenis nilai yang ditampilkan (seperti dengan ReshapeOp atau BroadcastInDimOp), buat pemverifikasi untuk berisi logika verifikasi yang diperlukan. Operasi yang biasanya dapat disimpulkan, seperti AddOp, mungkin masih memerlukan pemverifikasi untuk melakukan verifikasi tambahan, karena memverifikasi batasan dari jenis nilai yang ditampilkan yang disediakan, yang tidak dapat diakses dalam metode inferensi jenis/bentuk.

  2. Untuk operasi dengan region (seperti ReduceOp/IfOp; daftar lengkapnya ada di sini): Builder yang dibuat secara otomatis tidak menggunakan region sebagai parameter, jadi jika builder ini melibatkan inferensi jenis, fungsi bentuk akan dipanggil dengan region kosong (lihat contoh ini).

    1. Jika region tidak diperlukan untuk inferensi jenis (seperti ReduceOp), masukkan logika verifikasi terkait region dalam pemverifikasi, bukan fungsi bentuk. Buat duplikat beberapa kode jika tidak dapat dihindari.

    2. Jika region diperlukan untuk inferensi jenis (IfOp/CaseOp/MapOp), fungsi bentuk juga harus memverifikasi bahwa region tidak kosong secara eksplisit, meskipun ODS mungkin sudah menjamin keberadaannya dalam definisi Op.

(P4) Menetapkan pedoman pengujian

Apakah kami perlu menambahkan/mempertahankan pengujian untuk verifikasi yang dicakup oleh ODS?

Kami tidak tahu. Pengujian harus berfokus pada pemverifikasi dan fungsi bentuk, sedangkan perubahan pada ODS memerlukan peninjauan kembali terhadap operasi ini.

Namun, berhati-hatilah dengan bagian yang hilang: misalnya, jika op berisi fitur SameOperandsAndResultShape, yang hanya memeriksa bentuk, bukan jenis elemen, verifikasi untuk jenis elemen operand/hasil masih memerlukan pengujian.

Di mana kita melakukan pengujian untuk pemverifikasi dan inferensi jenis?

ops_stablehlo.mlir berisi kasus positif dari operasi, dan (setidaknya) 1 pengujian negatif untuk setiap error verifikasi. Alat ini juga dapat memeriksa apakah jenis nilai yang ditampilkan yang disimpulkan kompatibel dengan (tidak sama dengan) jenis hasil sebenarnya.

infer_stablehlo.mlir memverifikasi keberadaan fungsi bentuk dari operasi demi baris dengan hlo_test_infer.get_return_type_components"(%x):... dan memeriksa apakah jenis yang disimpulkan sama persis seperti yang diharapkan. Satu tes positif per operasi secara umum.

Yang harus dilakukan

Saat menerapkan atau meninjau kembali pemverifikasi dan/atau fungsi bentuk operasi:

  1. Masukkan semua kasus positif dan kasus negatif di ops_stablehlo.mlir.

  2. Tambahkan satu uji positif di infer_stablehlo.mlir untuk menguji antarmuka.

  3. (Opsional) Jika operasi rumit dan dapat berisi banyak pengujian, pertimbangkan untuk menambahkan file pengujian terpisah bernama verify_<op_name>.mlir atau verify_<your_topic>.mlir dalam folder yang sama.