GraalVM Native Image ตรงตาม RISC-V

Jan 17 2023
ตอนนี้สามารถใช้ GraalVM Native Image บน RISC-V ได้แล้ว! ฉันจะอธิบายวิธีการรวบรวมแอปพลิเคชันสำหรับ RISC-V และการนำไปใช้งานที่นี่ ตามค่าเริ่มต้น Native Image จะใช้คอมไพเลอร์ Graal เพื่อสร้างรหัสเครื่อง แต่สามารถใช้คอมไพเลอร์ LLVM แทนได้โดยการเปิดใช้งานแบ็กเอนด์ LLVM (เอกสารประกอบ)

ตอนนี้สามารถใช้ GraalVM Native Image บน RISC-V ได้แล้ว! ฉันจะอธิบายวิธีการรวบรวมแอปพลิเคชันสำหรับ RISC-V และการนำไปใช้งานที่นี่ ตามค่าเริ่มต้น Native Image จะใช้คอมไพเลอร์ Graal เพื่อสร้างรหัสเครื่อง แต่สามารถใช้คอมไพเลอร์ LLVM แทนได้โดยการเปิดใช้งานแบ็กเอนด์ LLVM ( documentation ) หนึ่งในเหตุผลสำคัญสำหรับการใช้ LLVM คือรองรับสถาปัตยกรรมที่หลากหลาย หมายความว่าเราไม่จำเป็นต้องใช้คอมไพเลอร์ Graal สำหรับสิ่งเหล่านี้ ซึ่งเป็นขั้นตอนที่ยากที่สุดในการเพิ่มการรองรับสำหรับสถาปัตยกรรมใหม่ เพื่อสาธิตสิ่งนี้ ฉันได้ปรับแบ็ก เอนด์ Native Image LLVM สำหรับเครื่อง RISC-V ภายใต้ Linux ด้วยGraalVM dev build

RISC-V

RISC-V เป็นสถาปัตยกรรมชุดคำสั่งแบบโอเพ่นซอร์ส (ISA) ที่สร้างขึ้นในปี 2010 ความแตกต่างที่สำคัญระหว่างสถาปัตยกรรมนี้กับผู้นำในปัจจุบันของตลาดคือความจริงที่ว่า RISC-V เป็นโอเพ่นซอร์ส แม้ว่าจุดประสงค์แรกในการใช้งานคือเพื่อการวิจัยและการศึกษา แต่ปัจจุบันความสนใจของอุตสาหกรรมก็เพิ่มขึ้น

จะใช้ ISA จำนวนเต็มฐานอย่างง่าย ซึ่งหลีกเลี่ยงรูปแบบสถาปัตยกรรมไมโครที่เฉพาะเจาะจงมากเกินไปและคุณสมบัติที่ปรับให้เหมาะสมมากเกินไปซึ่งออกแบบมาสำหรับโดเมนเฉพาะ ลดต้นทุนและปรับปรุงประสิทธิภาพสำหรับงานที่ตรงไปตรงมามากขึ้น สำหรับการใช้งานที่ซับซ้อนยิ่งขึ้น คุณสามารถเพิ่มส่วนขยายที่ด้านบนของ ISA ฐานได้ เช่น รองรับการคูณ ทศนิยม เวกเตอร์ และอื่นๆ ส่วนขยายบางส่วนได้รับการกำหนดไว้ล่วงหน้า แต่ก็สามารถกำหนดเองได้เช่นกัน

การสาธิตของไมโครนอต

เพื่อแสดงความแตกต่างของประสิทธิภาพระหว่างการทำงานบน JVM และ Native Image เราได้ทำการสาธิตตามแอปพลิเคชัน Micronaut ซึ่งเป็นเว็บเซิร์ฟเวอร์ขนาดเล็กบนโปรแกรมจำลอง RISC-V สามารถดูแหล่งที่มาของการสาธิตได้ที่นี่

การเริ่มต้นเซิร์ฟเวอร์ Micronaut โดยใช้แอปพลิเคชันที่คอมไพล์ด้วย Native Image:

__  __ _                                  _   
|  \/  (_) ___ _ __ ___  _ __   __ _ _   _| |_ 
| |\/| | |/ __| '__/ _ \| '_ \ / _` | | | | __|
| |  | | | (__| | | (_) | | | | (_| | |_| | |_ 
|_|  |_|_|\___|_|  \___/|_| |_|\__,_|\__,_|\__|
Micronaut (v3.6.0)

16:52:29.965 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 305ms. Server Running: http://fedora-riscv:8080

สร้างไบนารีข้ามสำหรับ RISC-V ด้วยแบ็กเอนด์ LLVM

เมื่อพิจารณาถึงวิธีปัจจุบันส่วนใหญ่ในการเรียกใช้ Linux บนเครื่อง RISC-V นั้นช้า ขอแนะนำให้สร้างข้ามไบนารีสำหรับ RISC-V Native Image รองรับด้วยข้อกำหนดเบื้องต้นบางอย่าง

RISC-V Toolchain พร้อม zlib

ต้องจัดเตรียม toolchain RISC-V ให้กับ Native Image ได้ที่นี่ เวอร์ชันของgccและglibcต้องเหมือนกันหรือเก่ากว่าเวอร์ชันที่ใช้โดยเครื่อง RISC-V

zlibรวมอยู่ใน toolchain ของ RISC-V แต่ต้องคอมไพล์ด้วยตนเองโดยใช้ไฟล์riscv-gcc. libz.aต้องย้ายไลบรารีที่ส่งออก ไปที่ path/to/built/toolchain/sysroot/usr/lib/.

CAPCache และ Static Libraries

CAPCache เป็นข้อมูลเกี่ยวกับ C ที่แท้จริงบนสถาปัตยกรรมเป้าหมาย ตลอดจนค่าของคุณสมบัติและแฟล็กของ CPU สามารถดาวน์โหลดได้ที่นี่

Native Image ต้องการ Java และ Graal ไลบรารีแบบคงที่ สามารถดาวน์โหลดได้ที่นี่

ขั้นตอนการสร้างข้ามไบนารี

ขั้นตอนต่อไปนี้จะอธิบายวิธีการสร้างไบนารีข้ามจากHelloWorld.javaไฟล์ อย่างง่าย

ขั้นตอนแรกคือการปฏิบัติตามข้อกำหนดเบื้องต้นที่กล่าวถึงข้างต้น

จากนั้น ดาวน์โหลดdev build ของ GraalVMพร้อมกับ Native Image

สุดท้าย เรียกใช้คำสั่งต่อไปนี้:

$JAVA_HOME/bin/javac Helloworld.java
$JAVA_HOME/bin/native-image HelloWorld -H:CompilerBackend=llvm \
    -Dsvm.targetPlatformArch=riscv64 -H:CAPCacheDir=/path/to/capcache \
    -H:CCompilerPath=/path/to/riscv-gcc -H:CustomLD=/path/to/riscv-ld \
    -H:CLibraryPath=/path/to/static-libraries \
    --add-exports=jdk.internal.vm.ci/jdk.vm.ci.riscv64=org.graalvm.nativeimage.builder

  • -Dsvm.targetPlatformArch=riscv64ทำให้คุณสามารถระบุสถาปัตยกรรมเป้าหมายได้
  • -H:CompilerBackend=llvmระบุว่าเราใช้แบ็กเอนด์ LLVM
  • -H:CAPCacheDir=/path/to/capcacheจัดเตรียม CAPCaches ที่คำนวณไว้ล่วงหน้าให้กับ Native Image
  • -H:CCompilerPath=/path/to/riscv-gccให้gccจาก toolchain RISC-V ไปยัง Native Image
  • -H:CustomLD=/path/to/riscv-ldให้ldจาก toolchain RISC-V ไปยัง Native Image
  • -H:CLibraryPath=/path/to/static-librariesจัดเตรียมไลบรารีแบบสแตติกให้กับ Native Image

คำนวณ CAPCache และคอมไพล์ Static Libraries ด้วยตนเอง

หากต้องการขอรับ CAPCache หรือไลบรารีแบบคงที่ด้วยตนเอง วิธีหนึ่งคือสร้าง Native Image บน RISC-V จากแหล่งที่มา สามารถทำได้โดยใช้คำสั่งต่อไปนี้

git clone https://github.com/oracle/graal.git
git clone https://github.com/graalvm/mx.git
export PATH=$PWD/mx:$PATH
cd graal/substratevm
mx fetch-jdk
# Choose one of the jdk version and run the provided export command
export SKIP_LIBRARIES=true
mx build

ในการคำนวณ CAPCache ให้รันคำสั่งต่อไปนี้

$JAVA_HOME/bin/native-image HelloWorld -H:CompilerBackend=llvm \
    -H:+ExitAfterCAPCache -H:CAPCacheDir=/path/to/capcache -H:+NewCAPCache \
    -add-exports=jdk.internal.vm.ci/jdk.vm.ci.riscv64=org.graalvm.nativeimage.builder

สร้างไบนารี RISC-V โดยกำเนิด

แม้ว่าจะแนะนำให้สร้างข้ามไบนารี แต่ก็ยังสามารถสร้างไบนารีบนเครื่อง RISC-V ได้ ขั้นตอนนี้คล้ายกับการสร้างข้าม ไม่จำเป็นต้องใช้ toolchain อีกต่อไป เนื่องจากจะเป็นแบบเนทีฟ และ CAPCaches และไลบรารีสแตติกจะถูกจัดเตรียมโดยอัตโนมัติ ข้อแตกต่างสุดท้ายอยู่ในคำสั่งสุดท้าย:

$JAVA_HOME/bin/native-image HelloWorld -H:CompilerBackend=llvm \
    --add-exports=jdk.internal.vm.ci/jdk.vm.ci.riscv64=org.graalvm.nativeimage.builder

ในการเพิ่มเป้าหมาย RISC-V ให้ กับNative Image เราต้องทำการเปลี่ยนแปลงทั้งหมดที่อธิบายไว้ในเอกสารประกอบ อย่างไรก็ตาม มีการเปลี่ยนแปลงอื่นๆ ที่ไม่ได้กล่าวถึงที่เกี่ยวข้องกับ RISC-V

การดำเนินการ JVMCI

คอมไพเลอร์ Graal ขึ้นอยู่กับ Java Virtual Machine Compiler Interface (JVMCI) ซึ่งหมายความว่าคอมโพเนนต์ย่อย Java นี้จะต้องถูกนำไปใช้เพื่อใช้ Native Image เนื่องจากขึ้นอยู่กับคอมไพเลอร์ Graal แม้ว่าแบ็กเอนด์ LLVM จะไม่ใช้คอมไพเลอร์ Graal ทั้งหมด แต่ก็ยังใช้ส่วนหน้า ดังนั้นจึงต้องการส่วนย่อยของ JVMCI การใช้ งานเซ็ตย่อยนี้สำหรับ RISC-V สามารถพบได้ที่นี่

บทสรุป

แบ็กเอนด์ RISC-V LLVM รองรับฟีเจอร์เกือบทั้งหมดที่แบ็กเอนด์ LLVM อื่นรองรับ!

ยังมีงานที่ต้องทำ เช่น เพิ่มการรองรับสำหรับ macOS และระบบปฏิบัติการอื่นๆ การปรับให้เหมาะสมเฉพาะเป้าหมายบางอย่างอาจน่าสนใจในการตรวจสอบ เนื่องจาก RISC-V มีรีจิสเตอร์เฉพาะบางอย่างที่สถาปัตยกรรมอื่นๆ ทั้งหมดไม่มี ตัวอย่างเช่น มีการลงทะเบียนเธรด ( x4)

เมื่อพิจารณาว่าใช้เวลาประมาณหกเดือนในการเพิ่มการสนับสนุน RISC-V ให้กับ Native Image โดยใช้แบ็กเอนด์ LLVM แนวคิดในการเพิ่มการสนับสนุนสำหรับเป้าหมายที่เป็นไปได้อื่นๆ เช่น WebAssembly นั้นน่าสนใจ ในความเป็นจริง การเพิ่มสถาปัตยกรรมอื่นๆ จะเข้าถึงได้มากขึ้น เนื่องจากแบ็กเอนด์ LLVM จะปล่อยส่วนข้อมูลเนทีฟอิมเมจออกมาในเร็วๆ นี้ ทำให้สามารถข้ามการเพิ่มข้อมูลเกี่ยวกับไฟล์ออบเจกต์ได้

เรายินดีรับฟังความคิดเห็นของคุณ! คุณ สามารถแชร์ผ่านSlack , GitHub , TwitterหรือMastodon