1 poin oleh GN⁺ 2024-08-28 | 1 komentar | Bagikan ke WhatsApp
  • RV64 DynaRec milik Box64 telah berkembang dari setahun lalu yang baru mampu menjalankan game Linux native sederhana, hingga kini bisa menjalankan The Witcher 3 di PC RISC-V
  • Pemicu kemajuannya adalah mulai dimungkinkannya penggunaan kartu grafis AMD; keterbatasan OpenGL berkurang sehingga lebih banyak program x86 bisa diuji dan bug bisa diperbaiki
  • Backend RV64 mengimplementasikan lebih sedikit instruksi x86 dibanding backend ARM64, dan instruksi AVX juga masih menjadi pekerjaan rumah besar di sisi RISC-V
  • Karena RISC-V kekurangan ekstraksi/penyisipan rentang bit serta instruksi atomik 16 byte, biaya translasi untuk emulasi x86 lebih besar dibanding AArch64 atau LoongArch64
  • The Witcher 3 benar-benar berjalan dengan box64, mencapai hingga 15fps di dalam game, dan mencapai kecepatan penuh di menu utama

Hingga The Witcher 3 Bisa Berjalan di RISC-V

  • Setahun lalu, RV64 DynaRec baru bisa menjalankan game Linux native yang relatif mudah dijalankan seperti Stardew Valley dan World of Goo
  • Saat itu ada dua bottleneck utama
    • Masih banyak bug DynaRec yang tersisa dalam proses menambahkan instruksi x86_64 dengan cepat ke backend RISC-V
    • GPU terintegrasi IMG pada VisionFive 2 dan LicheePi 4A hanya mendukung OpenGL ES dan tidak mendukung OpenGL
  • Dengan gl4es, sebagian dukungan OpenGL bisa diperoleh sehingga game seperti Stardew Valley dapat berjalan, tetapi itu belum cukup untuk game Linux yang lebih berat dan game Windows pada umumnya
  • Milk-V Pioneer dari Sophgo adalah PC RISC-V 64-core dan menyediakan slot PCIe yang dapat dipasangi kartu grafis
  • Kontributor lain, xctan, menemukan cara “menghubungkan” kartu grafis AMD ke VisionFive 2 melalui antarmuka M.2
  • Setelah kartu grafis AMD bisa digunakan, cakupan program x86 yang dapat diuji meluas, dan perbaikan bug RV64 DynaRec serta penambahan instruksi x86 dilakukan dalam jumlah besar
  • Hasilnya, The Witcher 3 langsung berjalan saat pertama kali dicoba

Kondisi Terkini RV64 DynaRec

  • Set instruksi x86 sangat besar, dan skala implementasinya berbeda untuk tiap backend
    • Backend ARM64 secara keseluruhan mengimplementasikan lebih dari 1.600 instruksi x86
    • Backend RV64 mengimplementasikan sekitar 1.000 instruksi x86
    • Lebih dari 300 di antaranya adalah instruksi AVX yang baru didukung, dan di RISC-V masih belum diimplementasikan sama sekali
  • Dalam implementasi instruksi SSE pun, RISC-V berada pada posisi yang kurang menguntungkan dari sisi performa
    • Backend RV64 mengimplementasikan instruksi SSE sebagai instruksi skalar
    • AArch64 menggunakan ekstensi Neon, sementara LoongArch64 menggunakan ekstensi LSX
    • Karena perbedaan ini, performanya jauh lebih rendah dibanding dua backend lainnya
  • RISC-V memiliki ekstensi vektor bernama RVV
    • Milk-V Pioneer mendukung ekstensi xtheadvector, varian dari RVV 0.7.1
    • SoC SpacemiT K1/M1 mendukung RVV 1.0 yang telah diratifikasi
    • Banana Pi F3 dan Milk-V Jupiter yang memakai SoC ini sudah bisa dibeli
  • box64 baru-baru ini menambahkan dukungan dasar RVV dan implementasi beberapa instruksi SSE umum
  • Pekerjaan pada RVV masih berada di tahap sangat awal, sehingga saat ini belum membantu peningkatan performa

Instruksi RISC-V yang Terutama Kurang untuk Emulasi x86

  • Dari sudut pandang emulasi x86, RISC-V termasuk yang paling rendah daya ekspresinya di antara tiga arsitektur yang didukung
  • Dibanding AArch64 dan LoongArch64, RISC-V kekurangan instruksi yang praktis, sehingga diperlukan lebih banyak instruksi untuk mengemulasikan operasi yang sama
  • Ada dua kemampuan yang sangat penting namun tidak tersedia
    • Kemampuan mengambil rentang bit tertentu dari satu register dan memindahkannya ke register lain
    • Kemampuan menyisipkan sebagian bit dari satu register ke rentang tertentu pada register lain
  • LoongArch64 dan AArch64 memiliki instruksi yang setara untuk hal ini
    • LoongArch64 menggunakan BSTRPICK.D dan BSTRINS.D
    • ARM64 menggunakan opcode UBFX dan BFI
  • RISC-V tidak memiliki instruksi yang setara, baik di ekstensi resmi maupun ekstensi vendor

Biaya Translasi yang Ditunjukkan Contoh ADD AH, BL

  • ISA x86 cenderung mempertahankan bit yang tidak diubah, sehingga manipulasi register parsial menjadi penting
  • Untuk ADD AH, BL, box64 harus melakukan hal berikut
    • Mengekstrak byte paling rendah dari RBX
    • Menambahkannya ke byte terendah kedua dari RAX
    • Menyisipkan kembali hasilnya ke byte terendah kedua dari RAX
    • Menjaga byte lain di RAX tetap apa adanya
  • Di LoongArch64, ini dapat diimplementasikan secara sederhana dan intuitif dengan BSTRPICK.D, ADD, dan BSTRINS.D
  • Di RISC-V, operasi yang sama harus menggabungkan shift, mask, AND, OR, dan lainnya sehingga membutuhkan 10 instruksi
  • Kasus seperti ini bukan contoh yang terisolasi; x86 memiliki banyak instruksi dengan bentuk serupa, sehingga implementasi di RISC-V menjadi lebih merepotkan

Keterbatasan Instruksi Atomik 16 Byte

  • x86 memiliki instruksi berprefiks LOCK untuk operasi atomik lock-free
  • box64 terutama mengemulasikannya dengan urutan LR/SC
    • LR/SC adalah singkatan dari Load-Reserved / Store-Conditionally
    • Misalnya, LOCK ADD [RAX], RCX dihasilkan sebagai LR.D, ADD, SC.D, dan percabangan bersyarat
  • Jika alamat RAX tidak selaras, prosesnya menjadi lebih rumit, tetapi secara umum cara ini bekerja dengan baik
  • Masalahnya adalah LOCK CMPXCHG16B
    • Instruksi ini membandingkan RDX:RAX dengan 16 byte di memori
    • Bergantung pada kondisinya, instruksi ini menukar RCX:RBX ke alamat memori tersebut
  • AArch64 dan LoongArch64 memiliki beberapa instruksi atomik 16 byte yang dapat digunakan untuk implementasi
  • RISC-V tidak memiliki instruksi yang setara, sehingga tidak dapat diimplementasikan selengkap arsitektur lain
  • Banyak program, termasuk game Unity, menggunakan LOCK CMPXCHG16B

Hasil Eksekusi Nyata

  • Meski masih ada keterbatasan, The Witcher 3 berjalan di RISC-V dengan box64
  • Performanya mencapai hingga 15fps di dalam game
  • Di menu utama, game berjalan pada kecepatan penuh
  • Untuk hasil dari mesin yang tidak dirancang dengan tujuan menjalankan game AAA, ini tergolong tidak buruk

1 komentar

 
GN⁺ 2024-08-28
Pendapat Hacker News
  • Sebagai orang yang tidak bekerja di bidang chip, saya penasaran: saat membuat perangkat lunak untuk RISC-V, apa yang perlu dilakukan berbeda oleh insinyur perangkat lunak?
    Saya bertanya-tanya apakah ukuran executable menjadi lebih besar sehingga lokalitas cache harus dioptimalkan secara agresif, dan apakah ada jenis perangkat lunak seperti game atau web server yang lebih cocok untuk CISC atau RISC

    • RISC-V dengan ekstensi instruksi terkompresi rata-rata cenderung menghasilkan ukuran kode yang lebih kecil daripada x86-64 atau ARM
      Tidak banyak hal yang secara mendasar perlu diubah dalam pendekatan perangkat lunak, dan perbedaan terbesar dibanding x86-64 adalah adanya 32 register sehingga nilai perantara bisa ditahan lebih banyak sebelum terdorong ke stack; ARM juga punya 32 register, jadi mirip. Biasanya ini bukan sesuatu yang perlu terlalu dipikirkan kecuali melakukan optimasi mikro
      Lebih detailnya, ekstensi vektor (V/RVV) tidak ada di ISA rv64gc dasar, sehingga tergantung target, optimasi SIMD mungkin tidak bisa didapat; popcount serta penghitungan jumlah nol di depan/belakang juga tidak ada di rv64gc dasar dan membutuhkan Zbb. Selain itu, pilihan tanpa cabang seperti a ? b : c juga membutuhkan 4–5 instruksi di rv64gc dasar, 3 instruksi dengan Zicond, tetapi bisa dilakukan dengan 1 instruksi di x86-64 dan aarch64
      Profil RISC-V sampai batas tertentu menyelesaikan dua masalah pertama. Misalnya, Android mensyaratkan rva23 yang mengharuskan RVV, Zbb, Zicond, dan sebagainya. Namun jika distribusi Linux menargetkan rva20/rv64gc, ekstensi semacam itu pada dasarnya tidak akan bisa dipakai dalam waktu lama pada kode prakompilasi yang tidak menyertakan dispatch dinamis. x86-64 juga punya masalah serupa, tetapi ARM memiliki ekstensi yang jauh lebih sedikit sehingga dampaknya lebih kecil; SVE adalah pengecualian terbesar, tetapi belum didukung secara luas
    • Sebagian besar tidak perlu melakukan apa pun secara berbeda. Kode yang ditulis dengan benar dalam bahasa tingkat tinggi seperti C seharusnya berjalan sama
      Perbedaan terbesar adalah model memori yang lemah, tetapi ini juga merupakan karakteristik yang ada pada sebagian besar arsitektur non-x86 seperti ARM, dan sejak awal kode tidak boleh bergantung pada model memori yang kuat
      Kepadatan kode executable secara historis tidak terlalu bagus di x86, jadi ukuran executable tidak bertambah sebesar yang dibayangkan. RISC-V dengan ekstensi instruksi terkompresi dan ARM 32-bit dengan ekstensi Thumb cukup padat
      Yang penting bukan CISC versus RISC, melainkan keberadaan dan kualitas instruksi vektor serta ekstensi kriptografi. Encoding/decoding video sangat bergantung pada instruksi vektor untuk performa yang baik, dan enkripsi seluruh disk atau hashing dapat terbantu oleh instruksi khusus yang mempercepat algoritma tertentu seperti AES dan SHA256
    • Set instruksi apa pun seharusnya cocok dengan hampir semua jenis beban kerja pada tingkat yang serupa. Jika Anda melakukan pemrograman assembly, perbedaannya akan terasa, tetapi jika membuat dengan Python atau Unity, hampir tidak menjadi masalah
      Intinya lebih ke terbebas dari paten ARM dan melakukan awal baru berdasarkan pelajaran yang telah dipetik
  • Saya jadi teringat orang Rusia terkenal yang menjalankan Atomic Heart di Elbrus 8S
    Elbrus punya penerjemah native, dan setahu saya cukup bagus. Atomic Heart kurang lebih bisa dimainkan pada sekitar 15–25fps

  • Tulisan ini agak kurang dalam menjelaskan bagian “dasar”. Saya kira dijalankan dengan semacam port Wine, tetapi sebenarnya tampaknya ISA x86_64 diimplementasikan dengan cara tertentu di atas chip RISC-V
    Akan bagus kalau ada yang bisa menjelaskan lebih lanjut bagaimana bagian itu bekerja

    • Penjelasan dasarnya ada di sini: https://box86.org/
      Memang emulator, tetapi sebagian library “sistem” seperti libc, libm, SDL, dan OpenGL menggunakan versi native, sehingga mudah diintegrasikan dengan sebagian besar aplikasi, dan dalam beberapa kasus performanya bisa sangat tinggi secara mengejutkan. Wine juga bisa dikompilasi dan dijalankan secara native
  • Hasil yang mengejutkan. Ini jumlah pekerjaan yang luar biasa besar, dan dalam beberapa kasus tampaknya sudah menyentuh batas RISC-V
    Instruksi untuk mengumpulkan/menyebarkan bit sepertinya perlu masuk sebagai ekstensi

    • Saya juga ingin melihat hasil pengujian dengan game yang lebih banyak bergantung pada core grafis daripada CPU. Mungkin Divinity 2 akan cocok
  • Dalam konteks emulasi x86, menarik bahwa di antara tiga arsitektur yang didukung, RISC-V adalah yang paling kurang ekspresif
    Di kelas sejarah ilmu komputer, saya belajar bahwa RISC adalah reduced instruction set computer, tetapi belakangan kalau melihat proposal profil RISC-V atau tulisan-tulisan terkait, banyak yang bernada “hanya perlu beberapa instruksi lagi untuk kesetaraan fitur”. Saya paham bahwa RISC-V bagi banyak orang adalah alternatif yang praktis untuk platform lain, tetapi saya juga penasaran apakah ini berarti impian RISC sudah mati

    • Sejauh yang saya pahami, RISC yang sebenarnya bukan “set instruksi yang benar-benar minimal secara absolut”, melainkan lebih dekat ke “jangan masukkan fitur pintar demi kenyamanan programmer assembly, dan sebisa mungkin serahkan ke compiler alih-alih ke silikon front-end”
      Dari ingatan saya saat membaca spesifikasi RISC-V, mereka cukup ketat untuk tidak menambahkan instruksi “kombo”, karena urutan instruksi yang umum bisa difusikan di front-end
      Kekurangan RISC-V dibanding x86/ARM tampaknya bukan karena fundamentalisme RISC, melainkan karena spesifikasinya dimulai dari chip embedded yang sangat dasar lalu seiring waktu menambahkan ekstensi untuk CPU aplikasi. RV32I dasar bahkan tidak punya perkalian integer. Sayangnya, perdebatan soal manipulasi bit dan ekstensi SIMD/vektor terlalu lama diselesaikan, dan akibatnya muncul celah fitur yang sekarang dibicarakan
    • Kalau ingin membuat set instruksi yang bisa diimplementasikan mahasiswa dalam satu semester, perlu penyederhanaan seperti membuat semua instruksi memiliki 2 input dan 1 output. Ini juga jauh lebih mudah bagi peneliti yang bereksperimen dengan desain prosesor
      Namun, sebagai gantinya beberapa instruksi yang praktis untuk performa tinggi dikeluarkan
      Pipeline yang sederhana juga punya keunggulan karena memakan lebih sedikit sumber daya engineering dari tim yang membuat desain berperforma tinggi, sehingga mereka bisa menghabiskan lebih banyak waktu untuk optimasi
      RISC pada umumnya adalah filosofi penyederhanaan, tetapi tingkatannya beragam. MIPS disederhanakan kira-kira seperti RISC-V, sedangkan ARM dan POWER lebih kompromistis, dan tampaknya tidak punya masalah besar bersaing dengan x86 di ranah performa tinggi
      Pasar prosesor punya banyak ceruk selain menjalankan aplikasi, seperti embedded dan akselerator. Untuk ceruk spesifik bernama core aplikasi, saya agak pesimistis terhadap RISC-V, tetapi jika dilihat lebih luas potensinya besar, mungkin bisa mendominasi beberapa ceruk komersial, dan sangat bagus sebagai alat pendidikan serta riset
    • Impian RISC adalah menyederhanakan desain CPU karena sebagian besar software ditulis dengan compiler, bukan langsung dalam assembly
      Ciri RISC klasik adalah sebagian besar instruksi manipulasi data hanya bekerja pada register, instruksi memori umumnya hanya load/store ke register, sehingga membutuhkan banyak register. Karena untuk meneruskan parameter harus memanipulasi stack secara langsung, stack juga dibuat sendiri, dan tanpa instruksi CALL/JSR, semuanya diimplementasikan dengan instruksi dasar yang melakukan load/store langsung ke register instruction pointer. Encoding instruksi dapat diprediksi dan semua instruksi berukuran sama. Beberapa arsitektur RISC juga selalu memiliki register yang membaca 0 dan tidak bisa ditulis, yang dipakai saat mengatur nilai menjadi 0
      Pendekatan ini berhasil, tetapi kemudian out-of-order execution dan SIMD menurunkan pentingnya. Stream instruksi mentah lebih mirip deklarasi jalur menuju hasil yang diinginkan, bukan berarti CPU benar-benar mengeksekusinya persis seperti itu. Di baliknya ada speculative execution, branch prediction, dan register renaming. SIMD lebih mirip ruang register yang lebar dan instruksi yang bekerja pada semua nilai di dalamnya. Pada akhirnya out-of-order execution dan SIMD mengambil kendali
    • Saya bahkan tidak yakin ada yang namanya impian RISC. Ada impian efisiensi, impian performa, impian biaya, dan impian kompleksitas rendah relatif terhadap biaya/performa/efisiensi, tetapi adakah orang yang menganggap RISC itu sendiri lebih penting daripada biaya, performa, efisiensi, dan kesederhanaan?
    • Dalam konteks ini, tujuannya adalah menjalankan kode yang sudah dikompilasi untuk x86_64 di RISC-V. Tuntutan “hanya perlu beberapa instruksi lagi untuk kesetaraan fitur” muncul karena mencoba menjalankan kode yang sudah dikompilasi untuk arsitektur yang memang punya instruksi tambahan seperti itu
      Secara teori, jika source code aslinya dikompilasi untuk RISC, binary yang dihasilkan akan sepenuhnya berbeda, dan instruksi-instruksi tertentu itu mungkin tidak diperlukan
      Secara realistis, rasanya tidak ada yang akan benar-benar mengompilasi game-game ini untuk RISC-V
  • Di screenshot RAM-nya terlihat 31GB, jelas lebih besar daripada spesifikasi maksimum development board yang disebutkan. Apakah di sini memakai sesuatu yang lain?

    • Itu board yang lebih lama, Pioneer
      Kalau sekarang, lebih baik memakai salah satu opsi terbaru yang punya beberapa core lebih cepat dengan implementasi RVA22 dan RVV 1.0
    • https://milkv.io/pioneer
    • milk-v pioneer dilengkapi 128GB RAM
  • Apakah ini 86Box? Menyenangkan mengingat kembali masa ketika saya membeli Amstrad PC1512
    Setelah menambahkan dua hard card 500MB dan ekspansi memori 128KB sehingga menjadi 640KB, rasanya jauh lebih seru. Awalnya hanya ada dua floppy 360KB, lalu beberapa tahun kemudian saya menambahkan hard card 32MB. Saya juga punya Borland TurboPascal dan Zortech C. Masa-masa yang menyenangkan

    • Bukan, ini Box64 dan merupakan proyek yang sama sekali berbeda
      Tapi saya juga ingat masa-masa memakai Amstrad PC1512
  • Saya penasaran apakah suatu hari akan ada sistem yang memuat beberapa CPU RISC-V besar bersama “GPU” yang diimplementasikan dengan sekumpulan CPU RISC-V kecil
    Mungkin bentuknya dengan fitur vektor yang sesuai, tetapi sebagai pertanyaan sampingan, saya juga penasaran apakah pendekatan vektor klasik alih-alih packed SIMD bisa berguna di GPU

  • Salah satu pencapaian Witcher 3 yang mengesankan secara teknis adalah port Switch, dan itu berjalan sangat baik
    Itu menunjukkan seberapa banyak yang bisa dicapai lewat optimasi, sekaligus seberapa banyak sumber daya yang terbuang di PC karena optimasi yang buruk

    • Faktor besarnya juga karena memakai tekstur dan model 3D dengan kualitas jauh lebih rendah, sehingga RAM untuk aset yang dibutuhkan jauh lebih sedikit
      Ini bukan perbandingan apel dengan apel, dan cakupan yang ditampilkan di layar sangat berbeda, jadi sulit untuk langsung menyimpulkan optimasi PC buruk
    • Jika resolusi rendering diturunkan ke 720p, atau 540p dalam mode handheld, pengaturan dibuat lebih rendah daripada minimum, dan sekitar 30fps bisa dianggap layak, maka PC spesifikasi minimum juga bisa menjalankan Witcher 3 dengan kondisi serupa
  • Semoga umpan balik tingkat ISA seperti ini sampai ke orang-orang di RVI

    • Di SIG efisiensi skalar, mereka sudah membahas instruksi penyisipan/ekstraksi bitfield
      Saat saya cek kemarin [1], contoh dalam tulisan itu sebenarnya sudah bisa dilakukan dengan 4 instruksi RISC-V. Hanya saja agak sulit terpikirkan
      # a0 = rax, a1 = rbx
      slli t0, a1, 64-8
      rori a0, a0, 16
      add a0, a0, t0
      rori a0, a0, 64-16
      [1] https://www.reddit.com/r/RISCV/comments/1f1mnxf/box64_and_ri...
    • Tidak ada satu pun yang baru dari semua ini
      Sebenarnya, ketiadaan ekstraksi bitfield adalah kesalahan yang terlalu jelas, jadi itu contoh favorit saya untuk menunjukkan betapa konyolnya ISA RISC-V. Yang kedua adalah tidak adanya mode pengalamatan yang waras
      Beberapa desain RISC-V yang lebih baik memang mengimplementasikan instruksi kustom untuk ini. Misalnya BEXTM di Hazard3: https://github.com/Wren6991/Hazard3/blob/stable/doc/hazard3....