- Box64’ün RV64 DynaRec’i, bir yıl önce basit yerel Linux oyunlarını çalıştırabilen seviyeden RISC-V PC’de The Witcher 3’ü çalıştırma aşamasına kadar ilerledi
- İlerlemenin tetikleyicisi AMD ekran kartı kullanımının mümkün hâle gelmesiydi; OpenGL kısıtları azalınca daha fazla x86 programı test etmek ve hataları düzeltmek mümkün oldu
- RV64 arka ucu, ARM64 arka ucuna göre daha az sayıda x86 komutu uyguluyor; AVX komutları da RISC-V tarafında hâlâ büyük bir iş olarak duruyor
- RISC-V’de bit aralığı çıkarma/yerleştirme ve 16 baytlık atomik komutlar eksik olduğundan, x86 emülasyonunda çeviri maliyeti AArch64 veya LoongArch64’e göre daha yüksek
- The Witcher 3, box64 ile gerçekten çalışıyor; oyun içinde en fazla 15fps’ye ulaşıyor, ana menüde ise tam hıza erişiyor
The Witcher 3’ün RISC-V’de çalışmasına giden yol
- Bir yıl önce RV64 DynaRec yalnızca Stardew Valley, World of Goo gibi nispeten çalıştırması kolay yerel Linux oyunlarını çalıştırabiliyordu
- O dönemde darboğazlar genel olarak iki taneydi
- RISC-V arka ucuna x86_64 komutlarını hızlıca ekleme sürecinde çok sayıda DynaRec hatası kalmıştı
- VisionFive 2 ve LicheePi 4A’nın IMG tümleşik GPU’su yalnızca OpenGL ES destekliyor, OpenGL desteklemiyordu
- gl4es ile bir miktar OpenGL desteği elde edilerek Stardew Valley gibi oyunlar çalıştırılabiliyordu, ancak daha ağır Linux oyunları ve tipik Windows oyunları için bu yeterli değildi
- Sophgo’nun Milk-V Pioneer’ı, ekran kartı takılabilen bir PCIe yuvası sunan 64 çekirdekli bir RISC-V PC
- Bir başka katkıcı olan xctan, VisionFive 2’ye M.2 arayüzü üzerinden AMD ekran kartı “bağlamanın” bir yolunu buldu
- AMD ekran kartlarının kullanılabilir hâle gelmesiyle test edilebilen x86 programlarının kapsamı genişledi; RV64 DynaRec hata düzeltmeleri ve x86 komutu eklemeleri büyük ölçekte yapıldı
- Bunun sonucunda The Witcher 3 ilk çalıştırıldığında doğrudan çalıştı
RV64 DynaRec’in mevcut durumu
- x86 komut seti çok büyük ve arka uçlara göre uygulama kapsamı da farklılık gösteriyor
- ARM64 arka ucu toplamda 1.600’den fazla x86 komutunu uyguluyor
- RV64 arka ucu yaklaşık 1.000 x86 komutunu uyguluyor
- Bunların 300’den fazlası yeni desteklenen AVX komutları; RISC-V tarafında ise bunlar henüz hiç uygulanmış değil
- SSE komutlarının uygulanmasında da RISC-V performans açısından dezavantajlı
- RV64 arka ucu SSE komutlarını skaler komutlar olarak uyguluyor
- AArch64 Neon uzantısını, LoongArch64 ise LSX uzantısını kullanıyor
- Bu fark nedeniyle performans diğer iki arka uca göre oldukça düşük
- RISC-V’de RVV adlı vektör uzantısı bulunuyor
- Milk-V Pioneer, RVV 0.7.1’in bir varyantı olan xtheadvector uzantısını destekliyor
- SpacemiT K1/M1 SoC, onaylanmış RVV 1.0’ı destekliyor
- Bu SoC’yi taşıyan Banana Pi F3 ve Milk-V Jupiter satın alınabiliyor
- box64’e yakın zamanda temel RVV desteği ve bazı yaygın SSE komutlarının uygulamaları eklendi
- RVV çalışmaları hâlâ çok erken aşamada olduğundan şu anda performans iyileştirmesine yardımcı olmuyor
x86 emülasyonu için RISC-V’de özellikle eksik olan komutlar
- x86 emülasyonu açısından RISC-V, desteklenen üç mimari arasında ifade gücü en düşük olanlardan biri
- AArch64 ve LoongArch64’e kıyasla kullanışlı komutlar eksik olduğu için aynı davranışı emüle ederken daha fazla komut gerekiyor
- Özellikle önemli iki işlev yok
- Bir register’dan belirli bir bit aralığını seçip başka bir register’a alma işlevi
- Bir register’daki bazı bitleri başka bir register’ın belirli bir aralığına yerleştirme işlevi
- LoongArch64 ve AArch64’te buna karşılık gelen komutlar var
- LoongArch64
BSTRPICK.DveBSTRINS.Dkullanıyor - ARM64
UBFXveBFIopcode’larını kullanıyor
- LoongArch64
- RISC-V’de buna karşılık gelen ne resmî bir uzantıda ne de üretici uzantılarında bir komut bulunuyor
ADD AH, BL örneğinin gösterdiği çeviri maliyeti
- x86 ISA, değişmeyen bitleri koruma eğiliminde olduğundan kısmi register işlemleri önem taşıyor
ADD AH, BLiçin box64’ün şu işleri yapması gerekiyorRBX’in en düşük baytını çıkarmak- Bunu
RAX’in sondan ikinci baytına eklemek - Sonucu tekrar
RAX’in sondan ikinci baytına yerleştirmek RAX’in geri kalan baytlarını olduğu gibi korumak
- LoongArch64’te bu,
BSTRPICK.D,ADD,BSTRINS.Dkullanılarak basit ve doğrudan şekilde uygulanabiliyor - RISC-V’de aynı işlem için shift, maske,
AND,ORvb. kombinasyonlar gerektiğinden 10 komut gerekiyor - Bu, tekil bir örnek değil; x86’da benzer biçimde çok sayıda komut olduğu için RISC-V uygulaması daha zahmetli hâle geliyor
16 baytlık atomik komutların kısıtları
- x86’da lock-free atomik işlemler için LOCK önekli komutlar bulunuyor
- box64 bunları çoğunlukla LR/SC dizileriyle emüle ediyor
- LR/SC, Load-Reserved / Store-Conditionally’nin kısaltması
- Örneğin
LOCK ADD [RAX], RCX,LR.D,ADD,SC.Dve koşullu dallanma biçiminde üretiliyor
RAXadresi hizalanmamışsa süreç daha karmaşık hâle geliyor, ancak genel olarak bu yöntem iyi çalışıyor- Sorun
LOCK CMPXCHG16B- Bu komut
RDX:RAX’i bellekteki 16 bayt ile karşılaştırıyor - Koşula bağlı olarak
RCX:RBX’i ilgili bellek adresiyle takas ediyor
- Bu komut
- AArch64 ve LoongArch64’te uygulamada kullanılabilecek bazı 16 baytlık atomik komutlar var
- RISC-V’de buna karşılık gelen bir komut bulunmadığından diğer mimariler kadar eksiksiz uygulanamıyor
- Unity oyunları dâhil birçok program
LOCK CMPXCHG16Bkullanıyor
Gerçek çalıştırma sonucu
- Kısıtlar hâlâ mevcut olsa da The Witcher 3, RISC-V’de box64 ile çalışıyor
- Performans oyun içinde en fazla 15fps’ye ulaşıyor
- Ana menüde tam hızda çalışıyor
- AAA oyun çalıştırmak amacıyla tasarlanmamış bir makineden çıkan sonuç için fena sayılmaz
1 yorum
Hacker News yorumları
Çip tarafında çalışmayan biri olarak merak ediyorum: RISC-V hedefli yazılım geliştirirken yazılım mühendisinin farklı yapması gereken ne var?
Çalıştırılabilir dosya boyutu büyüdüğü için önbellek yerelliğini agresif biçimde optimize etmek mi gerekiyor diye düşünüyorum; ayrıca oyunlar ya da web sunucuları gibi CISC/RISC taraflarından hangisine daha iyi uyan yazılım türleri var mı onu da merak ediyorum.
Yazılım yaklaşımında temelden değiştirilmesi gereken pek bir şey yok; x86-64'e kıyasla en büyük fark 32 register olması, yani ara değerleri stack'e taşırmadan önce daha fazlasını elde tutabilmesi. ARM'de de 32 register olduğu için benzer. Genelde mikro optimizasyon yapmıyorsanız çok dert edilecek bir şey değil.
Daha ayrıntıya girersek, vektör uzantısı (V/RVV) temel rv64gc ISA'da bulunmadığı için hedefe bağlı olarak SIMD optimizasyonlarından yararlanamayabilirsiniz; popcount ile baştaki/sondaki sıfır sayımı da temel rv64gc'de yok ve Zbb gerekiyor. Ayrıca
a ? b : cgibi dallanmasız seçim de temel rv64gc'de 4-5 komut, Zicond ile 3 komut gerektirirken x86-64 ve aarch64'te 1 komutla yapılabiliyor.RISC-V profilleri ilk iki sorunu bir ölçüde çözüyor. Örneğin Android, RVV, Zbb, Zicond vb. isteyen rva23'ü şart koşuyor. Ancak Linux dağıtımları rva20/rv64gc'yi hedeflerse, dinamik dispatch eklenmemiş önceden derlenmiş kodda bu uzantıları fiilen uzun süre kullanamazsınız. x86-64'te de benzer bir sorun var; fakat ARM'de uzantılar çok daha az olduğu için daha hafif. En büyük istisna SVE, o da henüz yaygın desteklenmiyor.
En büyük fark zayıf bellek modeli; bu ARM gibi çoğu x86 dışı mimaride de bulunan bir özellik ve zaten kodun güçlü bellek modeline bel bağlamaması gerekir.
Çalıştırılan kod yoğunluğu, tarihsel nedenlerle x86'da pek iyi olmadığı için çalıştırılabilir dosya boyutu sanıldığı kadar artmaz. Sıkıştırılmış komut uzantısı olan RISC-V ve Thumb uzantılı 32 bit ARM oldukça yoğundur.
Önemli olan CISC'e karşı RISC değil, vektör komutlarının ve kriptografi uzantılarının varlığı ve kalitesidir. Video kodlama/kod çözme iyi performans için vektör komutlarına büyük ölçüde dayanır; tam disk şifreleme veya hashing ise AES, SHA256 gibi belirli algoritmaları hızlandıran özel komutlardan fayda görebilir.
Esas mesele ARM patentlerinden özgürleşmek ve öğrenilen derslerle temiz bir başlangıç yapmak gibi.
Ünlü bir Rus'un Elbrus 8S üzerinde Atomic Heart çalıştırması aklıma geldi.
Elbrus'un yerel bir çeviricisi var ve bildiğim kadarıyla oldukça iyi. Atomic Heart 15-25 fps civarında bir ölçüde oynanabiliyordu.
Yazıda “temel” açıklama biraz eksik. Wine portu gibi bir şey kullanarak çalıştırdıklarını sanmıştım; ama aslında RISC-V çipi üzerinde x86_64 ISA'yı bir şekilde uygulamışlar gibi görünüyor.
Bunun nasıl işlediğini biraz daha açıklayabilecek biri olsa iyi olurdu.
Bir emülatör olsa da libc, libm, SDL, OpenGL gibi bazı “sistem” kütüphanelerinin yerel sürümlerini kullandığı için çoğu uygulamayla entegre kullanımı kolay; bazı durumlarda performans da şaşırtıcı derecede yüksek olabilir. Wine da yerel olarak derlenip çalıştırılabilir.
Şaşırtıcı bir sonuç. Muazzam bir emek var ve bazı durumlarda RISC-V'in sınırlarına dayanmış gibi görünüyor.
Bit toplama/dağıtma komutları uzantı olarak eklenmeli gibi.
x86 emülasyonu bağlamında desteklenen 3 mimari arasında RISC-V’nin ifade gücü en düşük olanı olması ilginç
Bilgisayar bilimi tarihi dersinde RISC’i “indirgenmiş komut kümesi bilgisayarı” olarak öğrenmiştik; ama son dönemdeki RISC-V profil önerilerine ya da yazılara bakınca çoğu “işlevsel eşdeğerlik için sadece birkaç komut daha gerekiyor” minvalinde. RISC-V’nin pek çok kişi için diğer platformlara kullanışlı bir alternatif olduğunu anlıyorum; ama bunun RISC rüyasının öldüğü anlamına gelip gelmediğini de merak ediyorum
RISC-V spesifikasyonunu okuduğumu hatırladığım kadarıyla, yaygın komut dizileri ön uçta kaynaştırılabildiği için “kombo” komutlar eklememe konusunda oldukça katıydı
x86/ARM’ye kıyasla RISC-V’nin eksikleri RISC köktenciliğinden çok, spesifikasyonun çok temel gömülü yongalardan başlayıp zaman içinde uygulama CPU’ları için uzantılar eklemesinden kaynaklanıyor gibi. Temel RV32I’de tamsayı çarpma bile yok. Ne yazık ki bit manipülasyonu ve SIMD/vektör uzantıları tartışmasını bitirmek çok uzun sürdü; bunun sonucunda da bugün konuşulan işlev boşluğu ortaya çıktı
Ancak bunun karşılığında yüksek performans için kullanışlı bazı komutlar dışarıda kalır
Basit bir pipeline’ın, yüksek performanslı tasarım yapan ekiplerin mühendislik kaynaklarını daha az tüketip optimizasyona daha fazla zaman ayırmalarını sağlaması gibi bir avantajı da vardır
RISC genel olarak bir basitleştirme felsefesidir, ama derecesi değişir. MIPS, RISC-V kadar basitleştirilmiştir; ARM ve POWER ise daha uzlaşmacıdır ve yüksek performans alanında x86 ile kapışmakta büyük bir sorun yaşamıyor gibi görünür
İşlemci pazarında uygulama çalıştırmanın dışında gömülü sistemler, hızlandırıcılar gibi birçok niş vardır. Uygulama çekirdeği denen belirli nişte RISC-V konusunda biraz kötümserim; ama daha geniş bakınca büyük potansiyeli var, bazı ticari nişlere hâkim olma ihtimali de var ve eğitim ile araştırma aracı olarak mükemmel
Klasik RISC’in özellikleri şunlardı: veri işleme komutlarının çoğu yalnızca register’lar üzerinde çalışır; bellek komutları genel olarak register’a load/store’dan ibarettir; bu yüzden çok sayıda register gerekir. Parametre aktarımı için stack’i doğrudan manipüle etmek gerektiğinden stack’i de doğrudan oluşturursunuz; CALL/JSR komutu olmadan, komut işaretçisi register’ına doğrudan load/store yapan temel komutlarla uygulanır. Komut kodlaması öngörülebilirdir ve tüm komutların boyutu aynıdır. Birçok RISC mimarisinde her zaman 0 okunan ve yazılamayan bir register da vardı; değerleri 0’a ayarlamak için kullanılırdı
Bu yöntem işe yaradı, ancak sonrasında out-of-order execution ve SIMD önemini azalttı. Ham komut akışı, istenen sonuca giden yolun bir bildirimi gibidir; CPU’nun bunu gerçekten birebir yürüttüğü anlamına gelmez. Arkasında speculative execution, branch prediction ve register renaming vardır. SIMD ise geniş bir register alanı ve içindeki tüm değerler üzerinde çalışan komutlara benzer. Sonuçta inisiyatifi out-of-order execution ve SIMD aldı
Teorik olarak özgün kaynak kod RISC için derlenirse tamamen farklı bir binary çıkar ve o belirli komutlara ihtiyaç olmayabilir
Pratikte ise birinin bu oyunları gerçekten RISC-V için derleyeceğini sanmıyorum
Ekran görüntüsünde RAM 31GB görünüyor; bu, bahsedilen geliştirme kartının maksimum özelliklerinden açıkça daha yüksek. Burada başka bir şey mi kullanılıyor?
Bugün olsa RVA22 ve RVV 1.0 uygulayan, daha hızlı birkaç çekirdeğe sahip güncel seçeneklerden birini kullanmak daha iyi olur
Bu 86Box mı? Amstrad PC1512 aldığım zamanları yeniden hatırlamak eğlenceliydi
500MB’lık iki hard card ve 128KB bellek genişletmesi ekleyip 640KB’ye çıkarmak onu çok daha eğlenceli hale getirmişti. Başta yalnızca iki 360KB disket sürücü vardı; birkaç yıl sonra da 32MB’lık bir hard card eklemiştim. Borland TurboPascal ve Zortech C de vardı. Güzel zamanlardı
Yine de Amstrad PC1512 kullandığım zamanları hatırlıyorum
Bir gün birkaç büyük RISC-V CPU ile, küçük RISC-V CPU’lardan oluşan bir demetle uygulanmış bir “GPU”yu birlikte taşıyan sistemler çıkacak mı merak ediyorum
Muhtemelen uygun vektör özellikleri eklenmiş bir biçim olurdu; yan bir soru olarak da packed SIMD yerine klasik vektör yaklaşımının GPU’larda faydalı olup olamayacağını merak ediyorum
Teknik açıdan etkileyici Witcher 3 başarılarından biri de Switch portuydu; gerçekten iyi çalışıyordu
Optimizasyonla ne kadar çok şey yapılabileceğini ve PC’de kötü optimizasyon yüzünden ne kadar çok kaynağın boşa harcandığını gösteriyor
Elma elmayla karşılaştırma değil; ekranda gösterilen kapsam ciddi biçimde farklıyken PC’de kötü optimizasyon olduğu sonucuna varmak zor
Bu tür ISA düzeyi geri bildirimlerin RVI tarafındaki kişilere ulaşması iyi olurdu
Dün kontrol ettiğimde [1], yazıdaki örnek zaten 4 RISC-V komutuyla yapılabiliyordu. Yalnız akla getirmesi biraz zor
# a0 = rax, a1 = rbxslli t0, a1, 64-8rori a0, a0, 16add a0, a0, t0rori a0, a0, 64-16[1] https://www.reddit.com/r/RISCV/comments/1f1mnxf/box64_and_ri...
Aslında bit alanı çıkarmanın eksik olması o kadar bariz bir hata ki, RISC-V ISA’nın ne kadar akıl almaz olduğunu gösteren en sevdiğim örnek. İkincisi ise düzgün bir adresleme kipinin olmaması
Daha iyi RISC-V tasarımlarından bazıları bunun için gerçekten özel komutlar uyguluyor. Örneğin Hazard3’ün BEXTM’i var: https://github.com/Wren6991/Hazard3/blob/stable/doc/hazard3....