1 คะแนน โดย GN⁺ 5 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • nbd-vram เป็นเดมอนขนาดเล็กที่ช่วยให้สามารถใช้ VRAM ที่ว่างอยู่ของ NVIDIA GPU บน Linux เป็นพื้นที่สว็อปที่มีลำดับความสำคัญสูงได้
  • เหมาะกับ โน้ตบุ๊กกราฟิกแบบไฮบริด ที่อัปเกรดหน่วยความจำได้ยากเพราะเป็นหน่วยความจำแบบบัดกรี และใช้ iGPU ของ AMD/ATI สำหรับแสดงผล โดยนำ VRAM ของ NVIDIA ที่ไม่ได้ใช้งานมาช่วยลดแรงกดดันด้านหน่วยความจำ
  • สภาพแวดล้อมทดสอบคือ AMD/ATI + RTX 3070 Laptop, RAM 16GB, VRAM 8GB, NVIDIA driver 580.159.03, kernel 6.17, Pop!_OS และจัดสรร VRAM 7GB เป็นสว็อป รวมกับ zram และ SSD swap แล้วได้หน่วยความจำที่ระบุตำแหน่งได้รวมราว 46GB
  • ลำดับการทำงานคือใช้ RAM ให้เต็มก่อน จากนั้น VRAM จะรับเพจที่ล้นผ่าน PCIe ต่อด้วย zram ที่บีบอัดด้วย CPU และสุดท้ายจึงค่อยใช้ SSD
  • เดมอนจะจัดสรร VRAM ผ่าน CUDA driver API และให้บริการอุปกรณ์บล็อกผ่านโปรโตคอล NBD(Network Block Device) บน Unix socket โดยใช้ไดรเวอร์ nbd ที่มีอยู่ในเคอร์เนลเพื่อเปิดเผยเป็น /dev/nbdX ให้ใช้งานเหมือนอุปกรณ์สว็อปทั่วไป
  • เส้นทางข้อมูลคือ kernel swap subsystem → /dev/nbdX → nbd kernel driver → Unix socket → nbd-vram daemon → cuMemcpyHtoD/DtoH → GPU VRAM
  • ไม่ต้องใช้เคอร์เนลโมดูลแยกหรือ NVIDIA kernel symbol จึงสามารถคงการทำงานไว้ได้โดยไม่ต้องรีบิลด์ใหม่หลังอัปเดตเคอร์เนลหรือไดรเวอร์
  • วิธีที่ใช้ NVIDIA P2P API ล้มเหลวบน GeForce รุ่นคอนซูเมอร์ เพราะ nvidia_p2p_get_pages_persistent คืนค่า EINVAL และวิธี ioremap_wc แบบเข้าถึง BAR1 โดยตรงก็ล้มเหลวเช่นกัน เนื่องจากการอ่านพื้นที่นอก display framebuffer ราว 16MiB จะได้ค่า 0 กลับมา
  • เส้นทางการคัดลอกผ่าน CUDA อย่าง cuMemcpyHtoD และ cuMemcpyDtoH สามารถทำงานกับ CUDA GPU ได้โดยไม่ต้องใช้สิทธิ์พิเศษ จึงทำให้การเข้าถึงผ่าน NBD เลี่ยงข้อจำกัดของ P2P และ BAR1 ได้
  • ความต้องการของระบบคือ NVIDIA GPU ที่รองรับ CUDA, NVIDIA driver ที่มี libcuda.so.1, โมดูล nbd ของ Linux kernel 3.0+, nbd-client, gcc, make และไม่จำเป็นต้องมี CUDA toolkit
  • หลังติดตั้งแล้ว systemd service vram-swap-nbd จะเริ่มทำงานอัตโนมัติเมื่อบูต และสามารถปรับเพดาน VRAM ที่จะใช้กับลำดับความสำคัญของสว็อปได้ผ่าน VRAM_SETUP_SIZE_MB และ VRAM_SWAP_PRIORITY ใน /etc/systemd/system/vram-swap-nbd.service
  • เดมอนจะลองใช้ขนาด VRAM ที่ร้องขอก่อน และหากหน่วยความจำ GPU ไม่พอ จะลดลงครั้งละ 512MiB เพื่อจัดสรรใหม่ ดังนั้น VRAM_SETUP_SIZE_MB จึงทำงานเป็นเพดาน ไม่ใช่ค่าขนาดบังคับ
  • หากเปิดการจัดการตามสถานะพลังงาน บริการจะหยุดอัตโนมัติเมื่อถอดไฟ AC หรือเมื่อแบตเตอรี่ต่ำกว่าค่ากำหนด และจะเริ่มใหม่เมื่อไฟกลับมา โดยคำสั่ง systemctl stop ที่สั่งเองจะไม่ถูกเขียนทับ
  • ในเบนช์มาร์กของ RTX 3070 Laptop นั้น NVMe เร็วกว่าในด้าน sequential throughput และ random I/O แบบต่อเนื่อง แต่ในด้าน latency ของการอ่าน 4K ที่ 1 request/sec นั้น VRAM มีค่าเฉลี่ย 335us ซึ่งเร็วกว่า NVMe ที่ 9.05ms ถึง 27 เท่า
  • เผยแพร่ภายใต้ MIT License และในรีโพซิทอรียังมี test-nbd.sh สำหรับ smoke test, test-fill.sh สำหรับตรวจสอบทั้งพาร์ทิชัน และสคริปต์เบนช์มาร์กสำหรับ throughput, IOPS และ latency มาด้วย

1 ความคิดเห็น

 
GN⁺ 5 시간 전
ความเห็นจาก Hacker News
  • ถ้าจัดการผ่าน CUDA ให้เหมือนเป็นที่เก็บไฟล์หรือเมานต์แบบหนึ่ง โอเวอร์เฮดจะสูง ดังนั้นถ้าใช้ BAR ก็น่าจะช่วยเพิ่มทั้ง throughput และ IOPS ได้ชัดเจน

  • ถ้าคำอธิบายคือมันเหมาะกับโน้ตบุ๊กที่ใช้หน่วยความจำแบบบัดกรีติดบอร์ดและไม่มีทางอัปเกรดได้ ก็ถือว่าตอบคำถามแรกที่ผุดขึ้นมาทันทีว่า ทำไมต้องสลับจาก RAM แพงไปยัง RAM ที่แพงยิ่งกว่า
    แม้กรณีใช้งานจะดูเฉพาะทาง แต่ในสถานการณ์ที่ สลับไป SSD การเอา VRAM ว่าง 8GB มาใช้ก็เป็นไอเดียที่ดีเวลาจำเป็น

    • อีกเหตุผลหนึ่งคือ บางครั้งมี VRAM อยู่แต่ไม่ได้ใช้งานตลอด
      เช่น ถ้าซื้อ GPU มาเพื่อเล่นเกม ตอนที่ไม่ได้เล่นเกม เดสก์ท็อปเรนเดอร์ก็ไม่ได้ต้องการ 16GB VRAM ดังนั้นก็น่าจะเอาไปใช้ทำอย่างอื่นได้
      แต่ต้องตั้งอยู่บนสมมุติฐานว่าเวลาจะเริ่มเกม ระบบสามารถคืน VRAM ที่ใช้เป็นสว็อปอยู่ได้ ซึ่งไม่แน่ใจว่าในทางปฏิบัติทำได้หรือไม่
    • ใช้ VRAM เป็น RAM ทั่วไปได้จริงไหม? เช่น ถ้ามีโมดูล RAM 16GB และ GPU มี 16GB VRAM จะทำให้ระบบแสดงว่าเป็น RAM 32GB ได้หรือเปล่า และผลกระทบจะเป็นอย่างไร
    • สมัยก่อนเรียกสิ่งนี้ว่า RAM disk และมันทำให้ Atari ST เร็วขึ้นมาก
      บน Amstrad PCW ที่พบได้บ่อยในสหราชอาณาจักรช่วงกลางยุค 80 ถึงกลางยุค 90 สามารถใช้ RAM ได้สูงสุด 512kB และแบ่งส่วนค่อนข้างใหญ่ไปทำเป็น RAM disk ได้
      ตอนคอมไพล์ด้วย Turbo Pascal ก็เร็วขึ้นมากเหมือนกัน :-)
  • ไอเดียนั้นดี แต่ที่นี่ดูเหมือนจะมีอะไรผิดพลาดอย่างมาก
    เขาบอกว่าบน RTX 3070 Laptop ได้ sequential throughput แค่ประมาณ 1.3 GB/s ทั้งที่ชิป RTX 3070 นี้เป็น PCIe 4.0 x16 ซึ่งควรได้ 64GB/s และ GDDR6 ขนาด 8GB เองก็มีแบนด์วิดท์ 448GB/s
    การสลับไป NVMe น่าจะเร็วกว่าเป็นสองเท่า แต่ latency จะสูงกว่า

    • PCIe 4.0 x16 คือ 32 GB/s ต่อทิศทาง และวิธีที่นำมาใช้ที่นี่ไม่ใช่วิธีที่คนจะเลือกถ้าต้องการประสิทธิภาพสูง
      แถมยังรันเบนช์มาร์กโดยใช้ ZRAM ซึ่ง ZRAM จะบีบอัดเพจก่อนเขียนลงสว็อป ผมไม่รู้แน่ชัดว่าโอเวอร์เฮดด้านประสิทธิภาพมากแค่ไหน แต่มีโอกาสสูงว่าค่อนข้างมาก
      อย่างแรกเลย มันต้องผ่านไดรเวอร์ nbd ที่ขึ้นชื่อว่าช้าเพราะเป็นโปรแกรมใน user space และยังใช้ bounce buffer ใน user space ก่อนส่งไปยัง GPU อีกด้วย ถ้าเคอร์เนลต้องสลับเพจ มันต้องคัดลอกไปยังบัฟเฟอร์ที่เปิดให้ user space เห็นก่อน จากนั้นโปรแกรม user space ต้องถูกปลุกขึ้นมาอีกครั้งเพื่อออกคำสั่ง CUDA แล้วคัดลอกเพจนั้นไปยังหน่วยความจำของอุปกรณ์
      nbd เองก็ไม่ได้รองรับ queue depth สูงหรือการรวมการเข้าถึงที่อยู่ติดกันได้ดีนัก ถ้าเคอร์เนลออกคำสั่งสลับเพจ 4K จำนวนมากโดยไม่รวมกัน แค่จะให้ได้ 4 GB/s ก็ต้องมีการสลับบริบทระหว่างเคอร์เนลกับ user space อย่างน้อยหนึ่งล้านครั้งต่อวินาทีแล้ว ยังไม่ต้องพูดถึง 64 GB/s นี่แค่ดูเฉพาะส่วน NBD ยังไม่รวมความซับซ้อนของไดรเวอร์ NVIDIA
      PCIe ขนส่งข้อมูลได้มากก็จริง แต่ถ้าจะเข้าใกล้แบนด์วิดท์เต็ม ๆ ต้องใช้ DMA engine ที่มีรายการเพจยาว ๆ ถ้าตั้งค่าการส่งข้อมูลทีละเพจ 4K บน PCIe ก็ไม่มีทางทำให้บัสอิ่มตัวได้เต็มที่
      เส้นทางการสลับไป NVMe ถูกปรับแต่งมาอย่างดีมาก ตัว swapper สามารถส่งรายการเพจให้ไดรเวอร์ NVMe ได้โดยตรง และคอนโทรลเลอร์ก็ดึงข้อมูลจาก RAM ด้วย DMA ได้โดยตรง จึงไม่มีทั้งการคัดลอกฝั่ง CPU และการสลับบริบทเลย
      ถ้าย้ายไปใช้ไดรเวอร์ ublk อาจหลีกเลี่ยง bounce buffer ใน user space ได้ และอาจปรับปรุงเพิ่มได้ด้วยการตั้งค่า CUDA copy แบบขนานผ่านหลาย write queue
    • ถ้าสลับไป NVMe ก็จะใช้ PE cycle ของ NAND ด้วย ทำให้สึกหรอเมื่อเวลาผ่านไป
      แต่ RAM หรือ VRAM ไม่เสื่อมจากการใช้งานแบบนั้น
  • บนเครื่องพัฒนาของผมมี 32GB RAM และมี 32GB VRAM ที่แทบไม่ได้ใช้เลยเวลาที่ไม่ได้รันโมเดล AI ดังนั้นไอเดียนี้ก็ไม่ได้แย่นัก

    • มันให้ความรู้สึกเหมือนร่างกายแบบ pcmasterrace ที่ท่อนบนใหญ่โตแต่ขาผอมลีบ
  • สงสัยว่าเขาจัดการกับ backpressure อย่างไร ถ้ามีคำขอจัดสรร VRAM เข้ามาในขณะที่ VRAM กำลังถูกใช้เป็นพื้นที่สว็อปจะเกิดอะไรขึ้น?
    บน X11 บัฟเฟอร์ถูกจัดสรรล่วงหน้าเลยไม่แย่มาก แต่บน Wayland การจัดสรรเป็นแบบไดนามิกกว่ามาก ถ้า VRAM หมด เดสก์ท็อปทั้งระบบอาจพังได้ง่าย
    ผมเคยเจออาการชนแบบนี้หลายครั้งตอนสลับเครื่องด้วย Hyprland+llama-server+KVM เพราะคืน VRAM ไม่ได้

  • การสร้าง อุปกรณ์สว็อป ในระดับผู้ใช้เป็นหนึ่งในปัญหาคลาสสิกที่เหมือนจะแก้ไม่ได้มานานแล้ว
    ถ้าดีมอนต้อง swap-in เพจหนึ่ง แต่การจะ swap-in เพจนั้นได้ต้อง swap-in เพจของดีมอนเองก่อน จะทำอย่างไร?
    อย่างน้อยก็เคยมีการถกกันแบบนี้ว่าเป็นเหตุผลที่ไมโครเคอร์เนลไม่มีวันใช้งานได้จริง ที่นี่ผมไม่แน่ใจว่าแนวทางแก้คืออะไร

    • แค่ให้ดีมอนฉลาดพอจะรู้ว่าเพจไหนเป็นของตัวเอง และกันไม่ให้เพจเหล่านั้นถูก swap-out ก็พอ
      เคอร์เนล Linux เองก็กันไม่ให้ text page ของตัวเองถูก swap-out อยู่แล้ว ดังนั้นวิธีแก้มีอยู่แล้ว และผมไม่เห็นเหตุผลว่าทำไมจะใช้กับการออกแบบไมโครเคอร์เนลไม่ได้
    • หลักการทั่วไปคือ สิ่งที่เกี่ยวข้องกับ paging จะต้องไม่ถูก paging เอง
      ถ้าล็อกหน่วยความจำทั้งหมดของดีมอนไว้ ปัญหานี้ก็กลายเป็นเรื่องเล็กน้อย
  • จำได้ว่าเคยทำอะไรคล้าย ๆ กันด้วยไดรเวอร์ MTD/phram ของ Linux: https://wiki.archlinux.org/title/Swap_on_video_RAM
    แต่ไม่แน่ใจว่าตอนนี้ยังเกี่ยวข้องอยู่ไหม เพราะไม่รู้ว่ามันโต้ตอบกับ DRM อย่างไร และจัดการเรื่องการจอง VRAM บางส่วนอย่างไร วิธีที่เสนอให้จำกัดผ่าน xorg.conf ตอนนี้อาจจะล้าสมัยมากแล้ว
    หน้านั้นยังมี FUSE filesystem ที่ทำบน OpenCL ด้วย: https://github.com/Overv/vramfs
    อันนี้อาจเข้ากันได้ดีกว่า

    • เมื่อก่อนผมเคยแมป หน่วยความจำวิดีโอ 8MB ผ่าน mtd มาใช้ และมันช่วยให้คอมไพล์ไดรเวอร์ X11 พวกนั้นได้ดีขึ้น
      ชวนให้คิดถึงวันเก่า ๆ
  • เคยเห็นอะไรคล้ายกันบน Windows เมื่อหลายปีก่อน
    มันเป็นไดรเวอร์ proof of concept เชิงทดลองที่ให้สร้าง RAM drive จาก VRAM ของการ์ด NVIDIA ได้ โดยการเข้าถึงแบบ sequential เร็วอย่างที่คาด แต่ random access ยังมีช่องให้ปรับปรุงอีกมาก
    GpuRamDrive สร้างไดรฟ์เสมือนที่รองรับด้วย GPU RAM: https://github.com/prsyahmi/GpuRamDrive
    ฟอร์กที่รองรับ AMD: https://github.com/brzz/GpuRamDrive/

  • คล้ายกัน แต่ใช้ OpenCL API จึงทำงานบน AMD ได้ด้วย
    เพียงแต่ไดรเวอร์ AMD มีบั๊กค่อนข้างเยอะ จนต้องนิยามก่อนว่าคำว่า “ทำงาน” หมายถึงอะไร: https://libguestfs.org/nbdkit-vram-plugin.1.html

  • ผมไม่เข้าใจว่าทำไม Apple Silicon Mac ที่มี RAM 32GB ยังเหลืออีก 20GB ที่ไม่ได้ใช้หรือเป็น “free” อยู่ ถึงยังใช้หรือถึงขั้นสร้าง swap file อยู่เลย
    ทำไมถึงไม่มีคำสั่งง่าย ๆ แบบ swapoff -a ของ Linux สำหรับ ปิดการใช้งาน swap file ทั้งหมด ได้เลย?
    ถ้าไม่ได้ตั้งใจจะลดอายุ SSD โดยเฉพาะ มันก็ดูงี่เง่าไปหน่อย
    ถ้ามีการตั้งค่าใน GUI สำหรับปิด swap file ก็คงดี และก็คงดีเหมือนกันถ้า Apple จะเลิกกับ “ขั้น” ของการจัดวาง system settings แบบปัจจุบันเสียที มันยังดูเหมือนสลัดคำพูดเมื่อเทียบกับแผง Preferences ตลอดหลายสิบปีที่ผ่านมา
    #Apple #Feedback #swapfile

    • หลักการของระบบ paging คือ หน่วยความจำหลักเป็นแคชของหน่วยเก็บข้อมูลรอง
      แนวคิดเรื่อง “หน่วยความจำที่ใช้งานได้” เอง ในอุดมคติก็ใกล้เคียงกับ “หน่วยความจำที่สามารถเรียกคืนได้อย่างรวดเร็วเพื่อนำไปใช้จุดประสงค์อื่น”
      ในบางช่วงเวลา การปล่อยให้ข้อมูลไฟล์ที่แคชไว้เข้ามาใช้พื้นที่นั้น อาจดีกว่าการเก็บ anonymous memory ไว้ในหน่วยความจำหลักต่อไป