1 điểm bởi GN⁺ 5 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • nbd-vram là một daemon nhỏ cho phép dùng phần VRAM nhàn rỗi của GPU NVIDIA làm không gian swap có mức ưu tiên cao trên Linux
  • Trên các laptop đồ họa lai nơi bộ nhớ được hàn chết nên khó nâng cấp và GPU AMD/ATI tích hợp đảm nhiệm xuất hình, công cụ này tận dụng VRAM NVIDIA đang nhàn rỗi để giảm áp lực bộ nhớ
  • Môi trường thử nghiệm là AMD/ATI + RTX 3070 Laptop, RAM 16GB, VRAM 8GB, NVIDIA driver 580.159.03, kernel 6.17, Pop!_OS; phân bổ 7GB VRAM làm swap để cùng với zram và swap trên SSD tạo thành khoảng 46GB bộ nhớ có thể định địa chỉ
  • Trình tự hoạt động là RAM đầy trước, sau đó VRAM hấp thụ các page bị tràn qua PCIe, tiếp theo zram nén bằng CPU, và cuối cùng mới dùng đến SSD
  • Daemon phân bổ VRAM bằng CUDA driver API, cung cấp thiết bị khối qua giao thức NBD(Network Block Device) trên Unix socket, và driver nbd tích hợp trong kernel sẽ hiển thị nó dưới dạng /dev/nbdX để dùng như một thiết bị swap thông thường
  • Đường đi dữ liệu là kernel swap subsystem → /dev/nbdX → nbd kernel driver → Unix socket → nbd-vram daemon → cuMemcpyHtoD/DtoH → GPU VRAM
  • Không cần module kernel riêng hay symbol kernel của NVIDIA, nên có thể duy trì hoạt động sau khi cập nhật kernel hoặc driver mà không cần build lại
  • Cách dùng NVIDIA P2P API thất bại trên GPU GeForce tiêu dùng khi nvidia_p2p_get_pages_persistent trả về EINVAL, còn cách truy cập trực tiếp BAR1 bằng ioremap_wc cũng thất bại vì việc đọc ngoài vùng framebuffer hiển thị khoảng 16MiB trả về 0
  • Đường sao chép CUDAcuMemcpyHtoDcuMemcpyDtoH hoạt động trên GPU CUDA mà không cần quyền đặc biệt, vì vậy truy cập qua NBD vượt qua được các hạn chế của P2P và BAR1
  • Yêu cầu gồm GPU NVIDIA hỗ trợ CUDA, driver NVIDIA có libcuda.so.1, module nbd của Linux kernel 3.0+, nbd-client, gcc, make; không cần CUDA toolkit
  • Sau khi cài đặt, dịch vụ systemd vram-swap-nbd sẽ tự chạy khi khởi động, và có thể điều chỉnh giới hạn VRAM sử dụng cùng mức ưu tiên swap bằng VRAM_SETUP_SIZE_MBVRAM_SWAP_PRIORITY trong /etc/systemd/system/vram-swap-nbd.service
  • Daemon sẽ thử trước với kích thước VRAM được yêu cầu, và nếu GPU thiếu bộ nhớ thì sẽ giảm dần theo đơn vị 512MiB để phân bổ, nên VRAM_SETUP_SIZE_MB hoạt động như mức trần chứ không phải dung lượng bắt buộc
  • Khi bật quản lý theo trạng thái nguồn, dịch vụ sẽ tự dừng khi rút nguồn AC hoặc khi pin xuống dưới ngưỡng, và sẽ khởi động lại khi nguồn được khôi phục; lệnh systemctl stop thủ công sẽ không bị ghi đè
  • Trong benchmark trên RTX 3070 Laptop, thông lượng tuần tự và I/O ngẫu nhiên duy trì của NVMe nhanh hơn, nhưng độ trễ đọc 4K ở 1 request/sec của VRAM trung bình 335us, nhanh hơn 27 lần so với 9.05ms của NVMe
  • Được phát hành theo giấy phép MIT, kho mã nguồn cũng cung cấp test-nbd.sh để smoke test, test-fill.sh để kiểm tra toàn bộ phân vùng, cùng các script benchmark cho thông lượng, IOPS và độ trễ

1 bình luận

 
Ý kiến trên Hacker News
  • Nếu xử lý qua CUDA như một kiểu lưu trữ tệp hay mount thì overhead sẽ lớn, nên có vẻ dùng BAR có thể cải thiện rõ rệt thông lượng hoặc IOPS

  • Nếu lời giải thích là nó dành cho laptop có bộ nhớ hàn chết, không có đường nâng cấp, thì điều đó trả lời cho thắc mắc tức thì là tại sao lại swap từ RAM đắt sang RAM còn đắt hơn
    Có vẻ trường hợp dùng khá hẹp, nhưng trong tình huống swap ra SSD, tận dụng 8GB VRAM đang nhàn rỗi là một ý tưởng hay khi cần

    • Một lý do khác là có VRAM nhưng không phải lúc nào cũng dùng đến
      Ví dụ, nếu mua GPU để chơi game thì lúc không chơi, desktop rendering đâu cần tới 16GB VRAM, vậy có thể dùng nó cho mục đích khác cũng được chăng
      Tuy vậy, điều này giả định hệ thống có thể giải phóng phần VRAM đang dùng làm swap khi khởi động game, và tôi không rõ thực tế có làm được không
    • Liệu có thể thật sự dùng VRAM như RAM thông thường không? Ví dụ nếu có module RAM 16GB và GPU có 16GB VRAM, liệu có thể khiến hệ thống hiển thị thành 32GB RAM không, và tác động sẽ là gì?
    • Ngày xưa người ta gọi kiểu này là RAM disk, và Atari ST đã nhanh lên khủng khiếp
      Trên Amstrad PCW, vốn khá phổ biến ở Anh từ giữa thập niên 80 đến giữa thập niên 90, bạn có thể dùng tối đa 512kB RAM, và có thể dành một phần khá lớn trong đó làm RAM disk
      Khi biên dịch bằng Turbo Pascal cũng nhanh lên đáng kể :-)
  • Ý tưởng thì hay, nhưng ở đây có gì đó sai sai khá lớn
    Họ nói thông lượng tuần tự trên RTX 3070 Laptop chỉ khoảng 1.3 GB/s, trong khi con chip RTX 3070 này là PCIe 4.0 x16 nên lẽ ra phải đạt 64GB/s, còn bản thân 8GB GDDR6 là 448GB/s
    Swap ra ổ NVMe có lẽ sẽ nhanh gấp đôi, nhưng độ trễ sẽ cao hơn

    • PCIe 4.0 x16 là 32 GB/s cho mỗi chiều, và cách triển khai này không phải kiểu người ta chọn khi muốn hiệu năng cao
      Benchmark cũng được chạy với ZRAM, mà ZRAM sẽ nén trang trước khi ghi vào swap. Tôi không rõ chính xác overhead hiệu năng là bao nhiêu, nhưng rất có thể là khá lớn
      Trước hết, chương trình user-space đang nằm trên driver nbd vốn nổi tiếng là chậm, và còn dùng cả bounce buffer ở user-space trước khi chuyển sang GPU. Khi kernel cần swap một trang, trước tiên nó phải sao chép vào buffer được lộ ra cho user-space, rồi chương trình user-space lại phải thức dậy và phát lệnh CUDA để chép trang đó sang bộ nhớ thiết bị
      nbd cũng không hỗ trợ tốt queue depth cao hay gộp các truy cập liền kề. Nếu kernel phát nhiều swap 4K page mà không gộp, thì chỉ để xử lý 4 GB/s cũng đã cần ít nhất một triệu lần chuyển ngữ cảnh kernel/user-space mỗi giây. 64 GB/s thì còn khỏi nói. Và đây mới chỉ là phần NBD, chưa tính độ phức tạp của driver NVIDIA
      PCIe có thể chuyển rất nhiều dữ liệu, nhưng để tiến gần tổng băng thông thì cần dùng DMA engine với danh sách trang dài. Nếu cấu hình truyền cho từng trang 4K trên PCIe thì không thể bão hòa hoàn toàn bus được
      Đường đi swap sang NVMe được tối ưu hóa rất mạnh. Swapper có thể gửi trực tiếp danh sách trang cho driver NVMe, còn controller sẽ DMA trực tiếp từ RAM nên không có copy phía CPU hay chuyển ngữ cảnh nào cả
      Nếu chuyển sang driver ublk thì có thể tránh được bounce buffer ở user-space, và cũng có thể thiết lập song song các bản sao CUDA bằng nhiều hàng đợi ghi để cải thiện thêm
    • Swap sang NVMe cũng tiêu hao chu kỳ PE của NAND, nên sẽ bị mài mòn theo thời gian
      RAM hay VRAM thì không bị xuống cấp chỉ vì sử dụng
  • Tôi có 32GB RAM trên máy phát triển và 32GB VRAM phần lớn nhàn rỗi khi không chạy mô hình AI, nên ý tưởng này không hẳn tệ

    • Cảm giác như kiểu thân trên lực lưỡng còn chân thì tong teo theo phong cách pcmasterrace
  • Tôi thắc mắc họ xử lý backpressure như thế nào. Nếu đang dùng VRAM làm không gian swap mà lại có yêu cầu cấp phát VRAM thì sao?
    Trên X11, buffer được cấp phát trước nên còn đỡ, nhưng trên Wayland việc cấp phát động hơn nhiều, nên nếu thiếu VRAM thì cả desktop có thể chết rất dễ
    Tôi từng gặp vài vụ crash kiểu này khi chuyển máy tính với Hyprland+llama-server+KVM mà không giải phóng được VRAM

  • Tạo thiết bị swap ở mức người dùng từ lâu đã là một trong những bài toán kinh điển không giải được triệt để
    Nếu daemon cần swap-in một trang, nhưng để swap-in trang đó thì trước tiên lại phải swap-in chính các trang của daemon thì phải làm sao?
    Ít nhất đã từng có tranh luận kiểu này như một lý do vì sao microkernel sẽ không bao giờ hoạt động. Tôi không rõ lời giải ở đây là gì

    • Chỉ cần daemon đủ thông minh để biết trang nào là của nó, và ngăn các trang đó bị swap-out
      Kernel Linux cũng ngăn các text page của chính nó bị swap-out, nên lời giải đã có sẵn, và tôi không thấy lý do gì nó không áp dụng được cho thiết kế microkernel
    • Nguyên tắc chung là thứ gì tham gia vào paging thì bản thân nó không được bị paging
      Chỉ cần khóa toàn bộ bộ nhớ của daemon đó lại là giải quyết chuyện này một cách khá đơn giản
  • Tôi nhớ trước đây từng làm thứ gì đó tương tự với driver MTD/phram của Linux: https://wiki.archlinux.org/title/Swap_on_video_RAM
    Chỉ là tôi không chắc giờ nó còn liên quan không, vì tôi không biết nó tương tác với DRM thế nào, hay xử lý việc dành riêng một phần VRAM ra sao. Cách đề xuất giới hạn bằng xorg.conf giờ có lẽ đã khá lỗi thời
    Trang đó cũng có một filesystem FUSE triển khai trên OpenCL: https://github.com/Overv/vramfs
    Có thể hướng này tương thích tốt hơn

    • Hồi xưa tôi từng map 8MB bộ nhớ video qua mtd để dùng, và nó đã giúp ích cho việc build mấy... driver X11 đó
      Gợi lại nhiều kỷ niệm
  • Tôi cũng từng thấy thứ tương tự trên Windows vài năm trước
    Đó là một driver proof-of-concept mang tính thử nghiệm, cho phép tạo RAM drive từ VRAM của card NVIDIA; truy cập tuần tự thì nhanh như mong đợi nhưng truy cập ngẫu nhiên vẫn còn nhiều chỗ để cải thiện
    GpuRamDrive tạo một ổ đĩa ảo được hậu thuẫn bởi GPU RAM: https://github.com/prsyahmi/GpuRamDrive
    Fork hỗ trợ AMD: https://github.com/brzz/GpuRamDrive/

  • Tương tự, nhưng dùng OpenCL API nên cũng chạy được trên AMD
    Chỉ là driver AMD khá nhiều bug, nên còn phải định nghĩa thế nào mới gọi là “chạy được”: https://libguestfs.org/nbdkit-vram-plugin.1.html

  • Tôi không hiểu vì sao trên Apple Silicon Mac có 32GB RAM, vẫn còn 20GB chưa dùng/"free", mà nó vẫn dùng hoặc thậm chí còn tạo swap file
    Tại sao lại không có một lệnh đơn giản như swapoff -a của Linux để vô hiệu hóa hoàn toàn swap file?
    Nếu mục tiêu không phải là cố tình làm giảm tuổi thọ SSD thì điều này có vẻ khá ngớ ngẩn
    Sẽ hay hơn nếu có thiết lập hệ thống trong GUI để tắt swap file, và Apple cũng có thể tiện thể vứt bỏ luôn cái “tầng” system settings/layout hiện nay. So với các bảng điều khiển tùy chọn ngày xưa sau ngần ấy năm, nó vẫn như một mớ từ ngữ lộn xộn
    #Apple #Feedback #swapfile

    • Nguyên lý của hệ thống phân trang là bộ nhớ chính là bộ đệm của bộ nhớ phụ
      Khái niệm “bộ nhớ khả dụng” một cách lý tưởng cũng gần với “bộ nhớ có thể nhanh chóng thu hồi cho mục đích khác” hơn
      Ở một số thời điểm, giữ bộ nhớ ẩn danh trong bộ nhớ chính kém hợp lý hơn việc để nội dung tệp đã cache chiếm chỗ đó