3 คะแนน โดย GN⁺ 2023-08-21 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • เป็นเครื่องมือสำหรับรัน การอนุมานโมเดล Diffusion ตระกูล SD, Flux และ Wan ด้วย C/C++ ล้วน โดยมุ่งเน้นการเป็นอิมพลีเมนต์แบบเบาโดยไม่มี external dependency
  • การพัฒนาสร้างอยู่บน ggml และเป็นโครงสร้างแบบ Plain C/C++ ที่ทำงานในลักษณะเดียวกับ llama.cpp
  • ขอบเขตของโมเดลที่รองรับแบ่งเป็นโมเดลภาพ โมเดลแก้ไขภาพ และโมเดลวิดีโอ โดยรองรับ SD1.x, SD2.x, SDXL, SD3/SD3.5, FLUX, Qwen Image, Wan2.1/Wan2.2, LTX-2.3 เป็นต้น
  • ขอบเขตฟีเจอร์รองรับ PhotoMaker, Control Net สำหรับ SD 1.5, LoRA แบบ stable-diffusion-webui, LCM/LCM-LoRA, latent decoding บนพื้นฐาน TAESD, การอัปสเกลด้วย ESRGAN, negative prompt และ tokenizer ที่รองรับ token weighting
  • แบ็กเอนด์ที่ใช้รันได้แก่ CPU, CUDA, Vulkan, Metal, OpenCL และ SYCL โดยฝั่ง CPU รองรับ AVX, AVX2 และ AVX512 บนสถาปัตยกรรม x86
  • แพลตฟอร์มที่รองรับคือ Linux, Mac OS, Windows และ Android โดยบน Android ใช้งานผ่าน Termux และ Local Diffusion
  • รองรับรูปแบบ weight ได้แก่ .ckpt, .pth, .pt, .safetensors, .gguf และโหมดแปลงไฟล์สามารถแปลง model weight เป็น .gguf หรือ .safetensors
  • ขั้นตอนใช้งานพื้นฐานคือดาวน์โหลดไบนารีที่ build ไว้ล่วงหน้าจาก releases page หรือ build จากซอร์ส จากนั้นดาวน์โหลด model weight แล้วรันสร้างภาพด้วยรูปแบบ ./bin/sd-cli -m ../models/v1-5-pruned-emaonly.safetensors -p "a lovely cat"
  • มีฟีเจอร์ปรับการใช้หน่วยความจำให้เหมาะสมด้วย Flash Attention และ VAE tiling processing ส่วนการจัดแบ็กเอนด์ขณะรันและการปรับปรุงประสิทธิภาพของ runtime กับพารามิเตอร์มีคู่มือแยกต่างหาก
  • ตัวเลือกด้าน reproducibility แบ่งเป็น --rng cuda และ --rng cpu โดยตั้งเป้าให้สอดคล้องกับ GPU RNG ของ stable-diffusion-webui และ RNG ของ ComfyUI ตามลำดับ
  • เอาต์พุต PNG จะฝังพารามิเตอร์การสร้างเป็นข้อความสตริงที่เข้ากันได้กับ webui
  • มีโปรเจ็กต์ wrapper สำหรับ Golang, C#, Python, Rust และ Flutter/Dart และ Jellybox, Local Diffusion, LocalAI, KoboldCpp ก็ใช้ stable-diffusion.cpp เป็นแบ็กเอนด์สำหรับสร้างภาพ
  • โปรเจ็กต์ยังอยู่ระหว่างการพัฒนาอย่างต่อเนื่อง และ API กับตัวเลือกบรรทัดคำสั่งอาจเปลี่ยนแปลงบ่อย

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

 
GN⁺ 2023-08-21
ความคิดเห็นจาก Hacker News
  • Llama.cpp/ggml เหมาะกับ LLM เป็นพิเศษ
    เพราะต้องใช้หน่วยความจำมาก, quantization ได้ผลดี, การสร้างโทเคนเป็นแบบอนุกรมอย่างน่าทึ่งและติดอยู่กับแบนด์วิดท์หน่วยความจำ จึงเหมาะกับ CPU และยิ่งเหมาะกับการ inference แบบ pipeline CPU/GPU อันเป็นเอกลักษณ์ของ ggml
    แต่ Stable Diffusion แตกต่างออกไป quantization ไม่ได้ผลดีเท่านั้น, UNet ใช้การคำนวณหนักมาก และการสร้างภาพแบบ batch ก็มีประสิทธิภาพและมีประโยชน์แม้กับผู้ใช้คนเดียว ดังนั้นจึงเหมาะกับ GPU/การ์ดจอออนบอร์ดมากกว่า และได้ประโยชน์มากจากความ hackable ของ implementation ใน Python
    สำหรับ Stable Diffusion ผมคิดว่าแนวทางที่ถูกคือใช้ machine learning compiler เพื่อสร้างไฟล์ executable AITemplate เร็วมากอยู่แล้ว https://github.com/VoltaML/voltaML-fast-stable-diffusion, ส่วน TVM Vulkan ก็ดูมีอนาคตมาก หากมีใครทำ demo implementation ให้เสร็จสมบูรณ์ https://github.com/mlc-ai/web-stable-diffusion
    แถมยังรักษาความ hackable ส่วนใหญ่ของ implementation PyTorch ล้วนไว้ได้ด้วย

    • โปรเจกต์ข้างต้นก็รองรับ GPU ได้ระดับหนึ่ง หากส่ง แฟล็กคอมไพล์ GGML ที่ถูกต้อง
      เช่นตอนคอมไพล์รองรับ GGML_CUBLAS และได้ความเร็วเพิ่มขึ้นค่อนข้างดีเมื่อเทียบกับ C/C++ ล้วน
    • ในทางกลับกัน นี่เหมาะกับคนที่ไม่มี NVIDIA GPU ที่มี VRAM 6GB ขึ้นไป แต่ยังอยากลองเล่นกับโครงข่ายประสาทเหล่านี้บนเครื่องตัวเอง
      แม้จะใช้เวลาหน่อย แต่ก็รันบนโน้ตบุ๊กเก่าได้
    • ถ้าจำไม่ผิด ผมเคยเห็น ความเร็วเพิ่มขึ้น ค่อนข้างดีจาก torch.compile ด้วย และจำได้ว่าเคยทำเอง
      จะลองดูว่าหาตัวเลขได้ไหม
  • ยอดเยี่ยมที่ implement ถึง CLIP ด้วย
    ถ้าแยกมันออกมาต่างหากแล้วคอมไพล์เป็น implementation แบบ WebAssembly ก็น่าจะเจ๋ง
    แก้ไข: ดูเหมือนมีคนทำ https://github.com/monatis/clip.cpp ไว้แล้ว ทีนี้ก็แค่ทำให้เป็น WebAssembly

    • พูดถึง CLIP แล้ว ผมกังวลอยู่เสมอว่าเมื่อ OpenAI กับ Google เปลี่ยนเข้าสู่โหมดแข่งขันกัน โมเดลระดับ CLIP รุ่นถัดไปอาจจะไม่ถูกเปิดเผยต่อสาธารณะ
      รู้สึกน่าเสียดายเมื่อคิดว่าอาจมี โมเดลระดับ CLIP ที่พัฒนากว่านี้อยู่ในตู้เซฟลับที่ไหนสักแห่งแล้ว
      แก้ไข: ผมไม่ได้หมายถึง CLIP-2 แต่หมายถึงความก้าวหน้าที่สำคัญในระดับเดียวกับ CLIP
  • การตั้งค่าง่ายจนน่าเหลือเชื่อ เลยลองทันทีเป็นครั้งแรก
    อยากรู้ว่าความเร็วประมาณไหนถึงจะถือว่าปกติ
    บน Linux ผมรันบน AMD Ryzen 7 5700G ด้วย cmake .. -DGGML_OPENBLAS=ON และมีแค่กราฟิกออนบอร์ด ไม่มี GPU แยก
    เมื่อรัน ./bin/sd -m ../models/sd-v1-4-ggml-model-f32.bin -p "a lovely cat" แต่ละ sampling step ใช้เวลาประมาณ 12 วินาที และการ sampling ทั้งหมดใช้เวลา 246.40 วินาที
    อยากรู้ว่านี่เป็นประสิทธิภาพที่ควรคาดหวังหรือเปล่า
    แก้ไข: OpenBLAS ไม่ได้ติดตั้งอยู่ ดังนั้นแฟล็กนั้นจึงไม่มีผล

    • อันนี้ดีเลย โดยพื้นฐานแล้วมันทำสิ่งที่ผมอยากได้เมื่อ 1 ปีก่อน[0]
      ตอนนั้นแทบทุกทางออกต้องใช้กอง dependency ของ Python และใช้เวลาติดตั้งนานมาก จนสุดท้ายล้มเหลวเพราะพื้นที่ดิสก์ไม่พอ
      จริง ๆ แบบตรงตัวเลย คือแทนที่พื้นที่ดิสก์หลายกิกะไบต์ด้วย ไบนารีขนาด 799KB ไฟล์เดียว แถมถ้าใช้รูปแบบ Q8_0 ซึ่งดูเหมือนจะเร็วที่สุด ก็ยังประหยัดข้อมูลได้อีกประมาณ 2.3GB
      แต่ดูเหมือนจะมีบั๊กกับขนาดภาพอื่นนอกจาก 512x512 ค่าเริ่มต้น บางขนาดอย่าง 544x544 มักทำให้ assert ล้มเหลว, ขนาดที่เล็กกว่า 512x512 บางครั้งสร้างภาพขยะ และขนาดที่เล็กกว่า 384x384 แทบจะเป็นแบบนั้นเสมอ
      [0] https://news.ycombinator.com/item?id=32555608
    • ต้อง quantize โมเดลก่อน แต่ประมาณ 12 วินาทีต่อรอบดูเหมือนจะถูกแล้ว
    • ใช้ CPU อย่างเดียว, quantization 8 บิต, Intel Core i7 4770S, RAM DDR3 16GB, พีซีไร้พัดลมอายุ 10 ปี ได้ 32 วินาทีต่อ sampling step และผลลัพธ์ปกติดี
  • implementation ด้าน AI ที่เป็น C/C++ มีเสน่ห์พิเศษบางอย่าง
    โค้ดให้ความรู้สึกสะอาดและตรงไปตรงมา ทำให้ทั้งวงการ AI ดูเหมือนจับต้องและเรียนรู้ได้
    เป็นเพราะ ecosystem ของ Python รกเกินไปหรือเปล่า?

    • การเขียนใหม่โดยทั่วไปช่วยเพิ่ม คุณภาพโค้ด และการแทนที่ dependency ด้วยโค้ดเฉพาะทางที่ทำแค่งานที่จำเป็นก็ช่วยเพิ่มคุณภาพโค้ดเช่นกัน
      เวอร์ชัน Python ก็ใช้โค้ด C และ C++ เพื่อความเร็ว แต่ที่นี่ทุกอย่างอยู่ในภาษาเดียว
      เรียกได้ว่ามีปัจจัยสามอย่างที่ทำให้โค้ดสะอาดทำงานร่วมกัน
  • รู้สึกดีที่ได้เห็นคนสายแมชชีนเลิร์นนิงออกจาก Python แล้วใช้ภาษาที่ใช้ฮาร์ดแวร์ได้อย่างเหมาะสมที่สุด และไม่ต้องจัดสภาพแวดล้อมพิเศษเพื่อบิลด์และรัน

    • เป็นการเปรียบเทียบที่ค่อนข้างแปลก
      ก่อนอื่น โปรเจกต์ต้นทางนี้ไม่ได้ใช้ GPU เหมือน llama.cpp แต่โค้ดแมชชีนเลิร์นนิง Python ส่วนใหญ่ใช้ GPU การเขียนโค้ด Python ที่ใช้ GPU ได้อย่างเหมาะสมที่สุดไม่ใช่เรื่องยาก จะเรียก GPU ว่าเป็นสภาพแวดล้อมพิเศษสำหรับบิลด์และรันก็ได้ แต่สำหรับปัญหานี้ GPU น่าจะเหมาะกว่ามาก
      อย่างที่สอง โปรเจกต์ต้นทางนี้ก็เหมือน llama.cpp คือหลังจากยืนยันแล้วว่าโมเดลเฉพาะอย่าง Stable Diffusion/LLaMA ทำงานได้ดี จึงค่อยสร้างโค้ดที่มีประสิทธิภาพและเฉพาะทางสูงขึ้นมา ในทางกลับกัน จุดที่ Python โดดเด่นคือ ขั้นตอนการทำโปรโตไทป์ ที่ยังหาโมเดลที่เหมาะสมไม่เจอ ผมยังไม่เคยเห็นการทำโปรโตไทป์ใน C++ ที่ง่ายและสะดวกขนาดนี้
      ไม่ได้ตั้งใจจะลดคุณค่างานยอดเยี่ยมที่ทีม llama.cpp ทำในพื้นที่แมชชีนเลิร์นนิงบน CPU เพียงแต่ปัญหาที่แก้นั้นต่างกันโดยสิ้นเชิง
    • คงจะดีกว่ามากถ้าโมเดลแมชชีนเลิร์นนิงทุกตัวมี C inference API ง่าย ๆ ให้เรียกใช้ได้โดยตรงจากแทบทุกภาษาและแพลตฟอร์ม โดยไม่ต้องเจอกับความวุ่นวายของ dependency และการตั้งค่าสภาพแวดล้อม
    • ในสแตกแมชชีนเลิร์นนิง องค์ประกอบที่สำคัญต่อประสิทธิภาพจริง ๆ ก็ไม่ได้ถูกเขียนด้วย Python อยู่แล้ว
      ข้างในเป็น CUDA, C, C++ ทั้งหมดมาตั้งนานแล้ว
      Python เป็นแค่ กาว ที่มีประสิทธิภาพมากในการเชื่อมทุกอย่างเข้าด้วยกัน
    • ขอบคุณคนที่ทำงานแบบนี้จริง ๆ
      นี่เป็นวิธีเดียวที่ผมเคยใช้รันโมเดลเหล่านี้ได้โดยไม่เจอปัญหาปวดหัว ความแตกต่างมันมากจริง ๆ ชุด CUDA กับ Linux ก็ไม่ดีนัก ส่วน AMD กับ Windows นี่แย่มาก คิดว่าคงไม่ใช่แค่ผมคนเดียว
    • น่าสนใจที่ CPU ของผมสามารถรันบางส่วนในนี้ใน รูปแบบ quantized ได้เร็วแทบพอ ๆ กับ GPU
      สุดท้ายแล้วทั้งหมดเป็นปัญหาเรื่องแบนด์วิดท์หน่วยความจำหรือเปล่า?
      สถาปัตยกรรม GPU ไม่ได้มีแค่พลังประมวลผล แต่ยังเป็นโครงสร้างที่วางหน่วยความจำสำหรับงานไว้ใกล้กับหน่วยคำนวณด้วย แต่ละหน่วยมีหน่วยความจำภายในที่ซิงก์กับหน่วยความจำส่วนกลาง นี่เป็นเหตุผลสำคัญที่ทำให้ GPU เก่งกับงานแบบนี้หรือเปล่า?
  • ดูเหมือนเป็น C++ แล้วทำไมถึงเขียนว่า C/C++?

    • เท่าที่เข้าใจ dependency หลักอย่าง ggml เขียนด้วย C
  • วันนี้เห็น repo นี้แล้วดึงมาลอง บิลด์ .dylib บน Mac และสร้าง binding จากไฟล์ header ที่ให้มาด้วยเครื่องมือ ffi-gen ของ Dart
    กำลังทดลองใช้กับ Flutter และใช้ FFI เพราะไม่อยากเปิด subprocess
    ผลลัพธ์คือเหลือไว้แต่อาการปวดหัวหนัก ๆ กับแอปที่พัง พรุ่งนี้จะลองใหม่ตอนหัวโล่ง
    ถึงอย่างนั้น repo นี้เองก็ยอดเยี่ยม และบน M1 ก็รันได้ภายในไม่ถึง 10 นาทีด้วย f16

  • เห็นตัวอย่าง ระดับการ quantization หลายแบบแล้วค่อนข้างน่าประทับใจ
    การเปลี่ยนจาก f16 เป็น q8_0 ดูเหมือนเป็นการเปลี่ยนทิศทางมากกว่าการสูญเสียคุณภาพ ผลลัพธ์ q5_1 ดูแยกจาก q8_0 ได้ยาก
    ในโมเดลความแม่นยำสูงจะสูญเสียความ deterministic ไป แต่ในทางปฏิบัติอาจใช้งานได้ค่อนข้างดี

  • มี benchmark ไหม?

    • มีหลายคนจับเวลาไว้ที่นี่ และดูเหมือนว่าจะใช้เวลาประมาณ 15~20 วินาทีต่อรอบ iteration ขึ้นกับ quantization และฮาร์ดแวร์
      https://github.com/leejet/stable-diffusion.cpp/issues/1
    • คอมไพล์ด้วยคำสั่ง cmake .. -DGGML_CUBLAS=ON -DCMAKE_CUDA_COMPILER=/opt/cuda/bin/nvcc แล้วใช้ NVIDIA GeForce RTX 2060 SUPER
      โมเดลถูกแปลงเป็น FP16
      ด้วยตัวเลือกนี้ เวลาแต่ละรอบ iteration อยู่ระหว่าง 8.5~9 วินาที และเวลารวมในการสร้างภาพหนึ่งภาพประมาณ 200 วินาที