4 คะแนน โดย GN⁺ 2023-10-04 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • OnnxStream เป็นไลบรารี inference ขนาดจิ๋วที่พยายามรัน Stable Diffusion 1.5 และ SDXL 1.0 Base บน Raspberry Pi Zero 2 ที่มี RAM 512MB โดยไม่เพิ่ม swap และไม่บันทึกข้อมูลกลางลงดิสก์
  • แยก inference engine ออกจาก WeightsProvider รองรับ DiskNoCache, DiskPrefetch รวมถึงการโหลด แคช และ prefetch แบบกำหนดเอง และยังรับ weights โดยตรงจาก HTTP เพื่อประมวลผลโดยไม่ต้องเขียนลงดิสก์ได้ด้วย
  • SDXL 1.0 Base ใช้ไฟล์ ONNX ที่ export จาก implementation ของ Hugging Face Diffusers 0.19.3 และการสร้างภาพ 10 steps บน Raspberry Pi Zero 2 ใช้เวลาประมาณ 11 ชั่วโมง
  • VAE decoder ของ SDXL ใช้ RAM 4.4GB ใน FP32 และแก้ได้ยากด้วย FP16 หรือ UINT8 เพียงอย่างเดียว จึงลดหน่วยความจำลงเหลือ 298MB ด้วยการถอดรหัสแบบ tiled ที่ซ้อนทับกันและ blending
  • เมื่อเทียบกับ OnnxRuntime บน CPU ใช้หน่วยความจำน้อยกว่าสูงสุด 55 เท่า แลกกับความเร็วที่อาจช้ากว่า 0.5–2 เท่า และมีข้อจำกัด เช่น batch size 1 และเน้นรองรับ ONNX operators บางส่วน

เป้าหมายและการออกแบบของ OnnxStream

  • OnnxStream เริ่มต้นด้วยเป้าหมายในการรัน Stable Diffusion 1.5 บน Raspberry Pi Zero 2
    • Raspberry Pi Zero 2 เป็นไมโครคอมพิวเตอร์ที่มี RAM 512MB
    • RAM/VRAM ขั้นต่ำที่แนะนำของ Stable Diffusion โดยทั่วไปคือ 8GB
    • เงื่อนไขเป้าหมายคือไม่เพิ่มพื้นที่ swap และไม่ offload ผลลัพธ์กลางลงดิสก์
  • เฟรมเวิร์ก machine learning ทั่วไปมักให้ความสำคัญกับ latency หรือ throughput ของ inference ทำให้ใช้ RAM มากได้ง่าย
  • OnnxStream เป็นไลบรารี inference ขนาดเล็กและแก้ไขได้ง่ายที่เน้น ลดการใช้หน่วยความจำให้เหลือน้อยที่สุด
  • โครงสร้างหลักคือการแยก inference engine ออกจากคอมโพเนนต์ที่ให้ model weights คือ WeightsProvider
    • คลาสที่สืบทอดสามารถ implement วิธีโหลด แคช และ prefetch พารามิเตอร์ของโมเดลได้
    • WeightsProvider แบบกำหนดเองสามารถดาวน์โหลดข้อมูลโดยตรงจาก HTTP server และประมวลผลโดยไม่ต้องอ่านหรือเขียนดิสก์ได้
    • implementation พื้นฐานคือ DiskNoCache และ DiskPrefetch
  • เมื่อเทียบกับ OnnxRuntime บน CPU ใช้หน่วยความจำน้อยกว่าสูงสุด 55 เท่า โดยช้ากว่าประมาณ 0.5–2 เท่า

การรัน Stable Diffusion 1.5

  • ตัวอย่าง Stable Diffusion 1.5 ใช้ OnnxStream เพื่อสร้างภาพด้วย ความแม่นยำของ VAE decoder ที่แตกต่างกัน
  • คอมโพเนนต์เดียวที่ไม่สามารถใส่ใน RAM ของ Raspberry Pi Zero 2 ได้คือ VAE decoder
    • สาเหตุคือ residual connection, tensor ขนาดใหญ่ และ convolution ขนาดใหญ่ภายในโมเดล
    • การใช้ single precision หรือ half precision อย่างเดียวไม่พอให้พอดีกับ RAM ของ Raspberry Pi Zero 2
    • วิธีแก้คือ 8-bit static quantization
  • ภาพจาก VAE decoder ความแม่นยำ W8A8 ถูกสร้างบน Raspberry Pi Zero 2 และเมื่อใช้ตัวเลือก MAX_SPEED ใช้เวลาประมาณ 1.5 ชั่วโมง
  • ภาพ W16A16 สำหรับเปรียบเทียบถูกสร้างบน PC โดยใช้ latent เดียวกัน

การรองรับ Stable Diffusion XL 1.0 Base

  • ตัวอย่าง Stable Diffusion ของ OnnxStream รองรับ SDXL 1.0 Base แต่ไม่รวม Refiner
  • ไฟล์ ONNX export จาก implementation ของ SDXL 1.0 ในไลบรารี Hugging Face Diffusers และใช้เวอร์ชัน 0.19.3
  • SDXL 1.0 มีต้นทุนการคำนวณสูงกว่า SD 1.5 มาก
    • ความแตกต่างที่ใหญ่ที่สุดคือสามารถสร้าง ภาพ 1024x1024 แทน 512x512 ได้
    • การสร้างภาพ 10 steps ด้วย Hugging Face Diffusers บน PC 12 คอร์และ RAM 32GB ใช้เวลา 26 นาที
    • VRAM ขั้นต่ำที่แนะนำของ SDXL โดยทั่วไปคือ 12GB
  • OnnxStream สามารถรัน SDXL 1.0 ด้วย RAM ต่ำกว่า 300MB จึงทำงานบน Raspberry Pi Zero 2 ได้ด้วย
    • ไม่เพิ่ม swap
    • ไม่มีการเขียนดิสก์ระหว่าง inference
    • การสร้างภาพ 10 steps บน Raspberry Pi Zero 2 ใช้เวลาประมาณ 11 ชั่วโมง

การปรับแต่งหน่วยความจำเฉพาะ SDXL

  • SDXL 1.0 ใช้ชุด optimization แบบเดียวกับ SD 1.5 แต่มีความแตกต่างบางส่วน
  • โมเดล UNET ใช้ UINT8 dynamic quantization เพื่อรันบน Raspberry Pi Zero 2 ด้วย RAM ต่ำกว่า 300MB
    • เป้าหมายการ quantize ถูกจำกัดไว้ที่ subset บางส่วนของ tensor กลางขนาดใหญ่
  • VAE decoder ของ SDXL 1.0 จัดการยากกว่า SD 1.5
    • VAE decoder ของ SDXL 1.0 ใหญ่กว่า 4 เท่า เมื่อเทียบกับ VAE decoder ของ SD 1.5
    • เมื่อรันด้วย FP32 precision บน OnnxStream จะใช้ RAM 4.4GB
    • ใน SD 1.5 สามารถลดการใช้ RAM ของ VAE decoder ลงเหลือ 260MB ได้ด้วย UINT8 static quantization
  • VAE decoder ของ SDXL 1.0 เกิด overflow ใน arithmetic แบบ FP16 และ activation มีช่วงค่ากว้าง ทำให้ได้ภาพคุณภาพดีจาก UINT8 quantization ได้ยาก
  • มีวิธีแก้ FP16 เช่น sdxl-vae-fp16-fix แต่แม้ลดหน่วยความจำลงครึ่งหนึ่งก็ยังเป็น 2.2GB ซึ่งยังมากเกินไปสำหรับ Raspberry Pi Zero 2
  • วิธีแก้สุดท้ายคือ tiled decoding ที่ได้แรงบันดาลใจจาก implementation ของ VAE decoder ใน Hugging Face Diffusers
    • tensor ผลลัพธ์จาก diffusion มี shape (1,4,128,128)
    • แบ่งออกเป็น tensor ที่ซ้อนทับกันขนาด shape (1,4,32,32) จำนวน 5x5 รวม 25 ชิ้น
    • แต่ละ tile ซ้อนทับกับ tile ด้านซ้ายและด้านบน 25%
    • ผลลัพธ์การ decode ของแต่ละ tile เป็น tensor (1,3,256,256) และถูก blend เข้าไปในภาพสุดท้าย
    • หากปิด blending จะเห็นขอบ tile แต่เมื่อเปิดแล้วจะไม่เห็นขอบในผลลัพธ์สุดท้าย
  • ด้วยวิธีนี้ การใช้ RAM ของ SDXL VAE decoder ลดลงจาก 4.4GB เหลือ 298MB

ฟีเจอร์ที่รองรับและ dependency

  • OnnxStream รวมฟีเจอร์ที่จำเป็นสำหรับ inference แบบประหยัดหน่วยความจำไว้เป็นชุดเล็ก ๆ
    • แยก inference engine กับ WeightsProvider
    • DiskNoCache, DiskPrefetch, WeightsProvider แบบกำหนดเอง
    • attention slicing
    • 8-bit unsigned asymmetric percentile dynamic quantization
    • W8A8 unsigned asymmetric percentile static quantization
    • calibration ของโมเดล quantized
    • รองรับ FP16
    • implementation ของ ONNX operators ที่ใช้บ่อย 25 ตัว
  • การประมวลผลรันแบบลำดับ แต่ operator แต่ละตัวทำงานแบบ multithread
  • implementation มีโครงสร้างเป็นไฟล์ implementation เดียวและ header file โดยคลาส XnnPack ครอบการเรียก XNNPACK
  • primitive สำหรับ acceleration บางส่วนพึ่งพา XNNPACK
    • MatMul
    • Convolution
    • element-wise Add/Sub/Mul/Div
    • Sigmoid
    • Softmax

การเปรียบเทียบประสิทธิภาพและข้อจำกัด

  • Stable Diffusion ประกอบด้วยโมเดล 3 ตัว
    • text encoder: 672 operations, 123 ล้าน parameters
    • UNET: 2050 operations, 854 ล้าน parameters
    • VAE decoder: 276 operations, 49 ล้าน parameters
  • การสร้างภาพ 10 steps ที่ batch size 1 ต้องรันดังนี้
    • text encoder 2 ครั้ง
    • UNET 20 ครั้ง
    • VAE decoder 1 ครั้ง
  • เมื่อใช้ FP16 UNET ความแตกต่างด้านหน่วยความจำและเวลาระหว่าง OnnxStream กับ OnnxRuntime มีมาก
    • OnnxStream: ประมาณ 0.133GB, 18.2–19.8 วินาที
    • OnnxRuntime: 5.085–7.353GB, 7.28–12.8 วินาที
    • OnnxStream ใช้หน่วยความจำน้อยกว่าสูงสุด 55 เท่า แต่ช้ากว่า 0.5–2 เท่า
  • FP32 text encoder ใช้ 0.147GB บน OnnxStream และ 0.641GB บน OnnxRuntime
  • FP32 VAE decoder ใช้ 1.004GB บน OnnxStream และ 1.330–2.026GB บน OnnxRuntime
  • ผลการเปรียบเทียบมีเงื่อนไขบางอย่าง
    • การรันครั้งแรกของ OnnxRuntime เป็น warm-up inference ก่อนนำ InferenceSession กลับมาใช้ซ้ำ
    • OnnxStream ออกแบบแบบ eager จึงไม่มีแนวคิด warm-up แต่การรันครั้งต่อ ๆ ไปอาจได้ประโยชน์จาก weights file cache ของ OS
    • ปัจจุบัน OnnxStream ไม่รองรับ input ที่ไม่ใช่ batch size 1
    • OnnxRuntime สามารถใช้ batch size 2 ในการรัน UNET เพื่อเร่ง diffusion ทั้งหมดได้มาก
    • การเปลี่ยน EnableCpuMemArena และ ExecutionMode ใน SessionOptions ของ OnnxRuntime ไม่ทำให้เกิดความแตกต่างอย่างมีนัยสำคัญในการทดสอบ
    • NCNN มีการใช้หน่วยความจำและเวลา inference ใกล้เคียงกับ OnnxRuntime มาก
    • สภาพแวดล้อมทดสอบคือ Windows Server 2019, RAM 16GB, CPU 8750H AVX2, SSD 970 EVO Plus, VMWare 8 virtual cores

Attention slicing และ quantization

  • เมื่อรัน UNET, attention slicing และ W8A8 quantization ของ VAE decoder สำคัญต่อการลดหน่วยความจำจนรันได้บน Raspberry Pi Zero 2
  • attention slicing ทำให้ไม่ต้อง materialize เมทริกซ์ Q @ K^T ทั้งหมดในการคำนวณ scaled dot-product attention ใน multi-head attention
  • เมื่อ attention head count ของโมเดล UNET เป็น 8 tensor shape เป็นดังนี้
    • Q: (8,4096,40)
    • K^T: (8,40,4096)
    • ผลลัพธ์ MatMul แรก: (8,4096,4096)
    • ที่ FP32 precision จะเป็น tensor 512MB
  • วิธีแก้คือแบ่ง Q ในแนวตั้ง แล้วทำ attention operation สำหรับแต่ละ chunk
    • shape ของ Q_sliced คือ (1,x,40)
    • x คือค่าที่ได้จากการหาร 4096 ด้วย onnxstream::Model::m_attention_fused_ops_parts
    • ค่าเริ่มต้นคือ 2 และปรับแต่งได้
  • วิธีนี้ลดการใช้หน่วยความจำรวมของโมเดล FP32 UNET จาก 1.1GB เหลือ 300MB
  • FlashAttention อาจเป็นทางเลือกที่มีประสิทธิภาพกว่า แต่ต้องเขียน custom kernel แยกตามสถาปัตยกรรมที่รองรับ เช่น AVX, NEON และในกรณีนี้จะต้องเลี่ยง XNNPACK

การแปลงโมเดลและวิธีรัน

  • OnnxStream รันโมเดลที่กำหนดไว้ใน path_to_model_folder/model.txt
    • model operations ทั้งหมดอยู่ใน model.txt รูปแบบ ASCII
    • weights file ต้องอยู่เป็นชุดไฟล์ .bin ในโฟลเดอร์เดียวกัน
  • ออบเจ็กต์ Model สามารถตั้งค่าพารามิเตอร์เสริมได้หลายอย่าง
    • ระบุ weights provider อื่น
    • อ่าน/เขียนไฟล์ activation clipping range สำหรับโมเดล quantized
    • โหมด calibration ของโมเดล
    • ใช้ FP16 arithmetic
    • ใช้ UINT8 arithmetic
    • ใช้ UINT8 dynamic quantization
    • เปิด attention slicing
    • ตั้งจำนวนส่วนแบ่ง attention
  • หากต้องการใช้ไฟล์ ONNX กับ OnnxStream ให้ export model.txt และไฟล์ weights .bin ด้วยโน้ตบุ๊ก onnx2txt.ipynb
  • เมื่อ export PyTorch nn.Module เป็น ONNX มีเงื่อนไขบางอย่าง
    • ต้องปล่อย dynamic_axes ว่างไว้เมื่อเรียก torch.onnx.export
    • OnnxStream ไม่รองรับ input แบบ dynamic shape
    • แนะนำอย่างยิ่งให้รัน ONNX Simplifier ก่อนแปลง

การ build และเตรียมรัน

  • สามารถ build ตัวอย่าง Stable Diffusion ได้บน Linux, Mac, Windows และ Termux
    • บน Windows ใช้ x64 Native Tools Command Prompt ของ Visual Studio Tools
    • บน Mac ต้องติดตั้ง cmake ด้วย brew install cmake
  • ก่อนอื่นต้อง build XNNPACK
    • เนื่องจาก prototype ของฟังก์ชัน XNNPACK อาจเปลี่ยนได้ทุกเมื่อ จึงมีขั้นตอน checkout ไปยัง commit ที่ตรงกับช่วงเวลาหนึ่ง
    • จุดอ้างอิงคือ master commit ก่อน 2023-06-27 00:00
  • จากนั้น clone repository ของ OnnxStream แล้ว build ด้วย cmake ใน src/build
    • MAX_SPEED=ON
    • ระบุ path ของ XNNPACK clone ด้วย XNNPACK_DIR
  • ตัวเลือก MAX_SPEED อาจเพิ่มประสิทธิภาพได้ แต่ใช้หน่วยความจำมากขึ้นตอน build
    • บน Windows ประสิทธิภาพดีขึ้นประมาณ 10%
    • บน Raspberry Pi ประสิทธิภาพดีขึ้น มากกว่า 50%
    • ไฟล์ executable ที่สร้างอาจไม่ทำงาน และเคยพบปัญหาในการทดสอบบน Termux
    • หากมีปัญหา แนะนำให้เปลี่ยนเป็น MAX_SPEED=OFF ก่อน
  • weights สำหรับตัวอย่าง Stable Diffusion 1.5 ดาวน์โหลดได้จาก Releases ของ repository และมีขนาดประมาณ 2GB
  • weights ของ Stable Diffusion XL 1.0 Base ดาวน์โหลดได้จาก Hugging Face และมีขนาดประมาณ 8GB

ตัวเลือกของตัวอย่าง Stable Diffusion

  • ไฟล์ executable ตัวอย่างควบคุมการเลือกโมเดล input/output prompt และวิธี decode ด้วยตัวเลือก command line
    • --xl: รัน Stable Diffusion XL 1.0 แทน Stable Diffusion 1.5
    • --models-path: ระบุโฟลเดอร์โมเดล Stable Diffusion
    • --ops-printf: แสดง operation ปัจจุบันระหว่าง inference ไปยัง stdout
    • --output: ระบุไฟล์ PNG output
    • --decode-latents: ข้าม diffusion แล้ว decode ไฟล์ latents ที่ระบุ
    • --prompt: ระบุ positive prompt
    • --neg-prompt: ระบุ negative prompt
    • --steps: ระบุจำนวน diffusion steps
    • --save-latents: บันทึก latents หลัง diffusion ลงไฟล์ที่ระบุ
  • มีตัวเลือกเกี่ยวกับ Raspberry Pi และ decoder แยกต่างหากด้วย
    • --decoder-calibrate: calibrate quantized VAE decoder เฉพาะใน SD 1.5
    • --decoder-fp16: ใช้ FP16 VAE decoder เฉพาะใน SD 1.5
    • --not-tiled: ไม่ใช้ tiled VAE decoder เฉพาะใน SDXL 1.0
    • --rpi: ตั้งค่าโมเดลให้รันบน Raspberry Pi
    • --rpi-lowmem: ใช้การตั้งค่าหน่วยความจำต่ำสำหรับ Raspberry Pi Zero 2 เฉพาะใน SDXL 1.0

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

 
GN⁺ 2023-10-04
ความคิดเห็นบน Hacker News
  • น่าสนใจ ประโยคสำคัญคืออันนี้: “OnnxStream อาจช้ากว่า OnnxRuntime เพียง 0.5~2 เท่า แต่ ใช้หน่วยความจำน้อยกว่าสูงสุดถึง 55 เท่า
    การแลกกันระหว่าง หน่วยความจำวิดีโอ/การใช้หน่วยความจำกับเวลาการอนุมาน ดูเหมือนจะเป็นประโยชน์ได้ ไม่ใช่แค่กรณีที่หน่วยความจำจำกัดอย่าง Raspberry Pi แต่รวมถึงสถานการณ์อื่น ๆ ด้วย
    ถ้าวิธี unload weights แบบนี้ทำให้ประมวลผล batch size ที่ใหญ่ขึ้นได้ภายในหน่วยความจำเท่าเดิมจริง ๆ ก็สงสัยว่าจะเพิ่ม throughput ได้มาก แม้ latency จะเพิ่มขึ้นหรือเปล่า

    • อยากเอาอันนี้ไปใช้กับ LLM ถ้าลดการกินหน่วยความจำได้ขนาดนั้น ก็จะโหลดโมเดลหลายตัวพร้อมกันบน GPU ตัวเดียวได้มากขึ้น และถ้า clock ตามทัน ก็อาจชดเชยการสูญเสียความเร็วอนุมานของแต่ละโมเดลได้สบาย
    • “ช้ากว่า 0.5~2 เท่า” นี่ไม่ใช่พิมพ์ผิดเหรอ? ถ้าช้ากว่า 0.5 เท่า ก็แปลว่า เร็วขึ้น 2 เท่า แทน
      คงตั้งใจจะเขียนว่า “ช้ากว่า 1.5~2 เท่า” มากกว่า
    • เท่าที่ผมอ่านแบบค่อนข้างง่าย ๆ ดูเหมือนว่าไม่ได้ลด memory bandwidth ที่ต้องใช้ แต่แค่ลดขนาด working set เท่านั้น
      โดยทั่วไปงานอนุมาน ถ้าเกินระดับ “โมเดลนี้ใส่ในระบบนี้ได้ไหม” ไปแล้ว มักจะติดคอขวดที่ memory bandwidth ดังนั้นเทคนิคนี้คงไม่ได้ช่วยมากนักในการเพิ่ม throughput ด้วย batch size ที่ใหญ่ขึ้น เป็นไปได้สูงว่าแค่อินสแตนซ์เดียวก็ทำให้ memory controller อิ่มตัวแล้ว
      แต่ในฝั่งการเทรนอาจจะช่วยได้ก็ได้
  • 11 ชั่วโมงนี่ทำให้นึกถึงสมัยทำ ray tracing บน Amiga 500 เลย งานเรนเดอร์ “สุดท้าย” นี่ชัดเจนว่าเป็นงานที่ต้องปล่อยข้ามคืน

    • ทุกวันนี้ก็ยังทำแบบนั้นบ้างเป็นครั้งคราว ray tracer แบบ bidirectional สมัยใหม่ใช้เทคนิคที่น่าสนใจได้ และผมอยากเห็น caustics อย่างเส้นสว่าง ๆ ที่เกิดในแอ่งน้ำ
      แต่ถึง caustics จะดูสว่าง ในเชิงสถิติแล้วเป็นปรากฏการณ์ที่ค่อนข้างหายาก ถ้าจะให้ได้จริง ๆ ก็ต้องปลดข้อจำกัดของเอนจินเรนเดอร์แล้วปล่อยให้รันทั้งคืนไปเลย
      ผลลัพธ์คือภาพฉากธรรมดา ๆ หนึ่งภาพจากศิลปินฝีมือไม่ถึง แต่มี caustics สวย ๆ คงต้องทำงานประจำต่อไป
    • เหตุผลที่ต้องรันเรนเดอร์คุณภาพต่ำก่อน ก็เพราะดีกว่า เสียเวลาแค่หนึ่งชั่วโมงเพื่อเช็กว่าถูกไหม แทนที่จะปล่อยให้ผิดแล้วเสียเวลาทั้งคืน
      ตอนนั้นผมคิดว่าคงต้องหางานอดิเรกอื่นแล้วล่ะ ก่อนหน้านั้นไม่นาน มีคนเก่งคนหนึ่งปล่อยเครื่องมือที่เรนเดอร์ให้ดูฉากล่วงหน้าด้วย OpenGL ออกมา บน Amiga คงใช้ไม่ได้ แต่บนเครื่องผมมันพอรันได้อย่างหวุดหวิด
    • บน 286 ของผมก็เหมือนกัน ตั้งค่า povray ไว้แล้วไปนอน จากนั้นเช้ามาก็ดูภาพก่อนออกไปโรงเรียน
    • ถึงจะเป็นช่วงหลังจากนั้น แต่ผมก็ทำคล้าย ๆ กันบน 386 ด้วย 3DSMAX สำเนาน่าสงสัย
    • ยังจำได้ตอนรันแฟร็กทัล Mandelbrot บน C64 การดีบักโค้ดยากมากจริง ๆ
  • ผมใช้ Stable Diffusion ผ่าน invoke.ai บน MBP อยู่ มีคำแนะนำเรื่องการปรับพารามิเตอร์ SD ให้ดีขึ้นไหม? ใช้พรอมป์เดียวกันและการตั้งค่าที่ดูเหมือนจะเหมือนกัน เช่น โมเดลเดียวกันอย่าง Euler A ก็ยังทำคุณภาพภาพให้เท่าที่เห็นบนอินเทอร์เน็ตไม่ได้เลย

    • ในบรรดาที่เคยลองมา อันนี้ดีที่สุด แต่ดูเหมือนจะไม่รองรับ Mac เป็น fork ของ Fooocus ที่มีฟีเจอร์เยอะ ซึ่งสร้างโดยผู้พัฒนา ControlNet เดิม คุณภาพจากพรอมป์สั้น ๆ น่าทึ่งมาก: https://github.com/MoonRide303/Fooocus-MRE
      สำหรับ SD 1.5 พื้นฐาน ผมใช้ Volta เพราะมันเร็ว: https://github.com/VoltaML/voltaML-fast-stable-diffusion/com...
      คุณภาพภาพ SD 1.5 ที่ดีจริง ๆ ต้องใช้โมเดลที่ fine-tune, LoRA, ControlNet และฟีเจอร์เสริมอื่น ๆ แบบไม่กั๊ก ตัวอย่างเช่น ให้ภาพพื้นฐานเป็นโครงสร้างอ้างอิง หรือกำหนดพรอมป์แยกตามพื้นที่เฉพาะในภาพ จริง ๆ แล้ว InvokeAI ก็มีฟีเจอร์เยอะ และมีฟีเจอร์เสริมแบบนี้ซ่อนอยู่ใน node UI มากมาย แต่ UI อื่นอย่าง Volta จะเผยให้ใช้ตรงกว่า
    • ใช้ custom weights อยู่ไหม? คงใช้อยู่แล้วแหละ แต่ความต่างระหว่าง weights RunwayML 1.5 พื้นฐานกับโมเดลที่ fine-tune มาเพื่อวัตถุประสงค์เฉพาะนั้นใหญ่มาก
      โดยทั่วไป โมเดล fine-tune ที่ให้ผลน่าประทับใจจะมีความอเนกประสงค์น้อยกว่า weights พื้นฐานมาก แต่ในการใช้งานจริงมักไม่ใช่ปัญหาใหญ่ และผลลัพธ์อาจดีขึ้นได้มาก
    • ผมเคยเจอประสบการณ์เดียวกันตอนใช้ Invoke.ai หรือ MochiDiffusion บน MBP M1 สิ่งเดียวที่ทำให้ได้คุณภาพภาพเทียบกับที่อื่นคือ Automatic1111(https://github.com/AUTOMATIC1111/stable-diffusion-webui)
      แม้จะต้องใช้เวลาและหน่วยความจำมากกว่า Invoke หรือการ์ดจอ Nvidia แต่ก็ไม่ได้แย่มาก ภาพคุณภาพมาตรฐาน 512x768px อยู่ที่ประมาณ 1~2 s/it ส่วนภาพคุณภาพสูง 1024x1536px ที่ใช้ Hires Fix อยู่ที่ประมาณ 14~20 s/it
    • ภาพพวกนั้นระบุไว้หรือเปล่าว่าออกมาจากตัวสร้างโดยตรง? วิดีโอกระบวนการที่ผมเห็นเริ่มจาก “เด็กผู้หญิงยืนอยู่ในทุ่งหญ้าสีเขียว” แล้วก็ทำ inpainting นานกว่าหนึ่งชั่วโมง เพื่อแก้มือหรือท่าทางอะไรพวกนั้น
    • Draw Things เพิ่ม โหมด seed ที่เข้ากันได้กับ CUDA แล้ว ทำให้บน Mac ก็สามารถทำภาพให้ตรงกับที่สร้างบนการ์ด NVDIA ได้
  • ถ้าเอาอันนี้ไปฝังไว้ใน กรอบรูปดิจิทัลหรือภาพแขวนผนัง แล้วให้มันรันได้ คงเจ๋งมาก

    • ก่อนหน้านี้ผมเคยทำสิ่งนี้ด้วยเวอร์ชันก่อนหน้าที่รัน Stable Diffusion บน Raspberry Pi Zero 2 W: https://hackaday.com/2023/09/19/e-paper-news-feed-illustrate...
      https://github.com/rvdveen/epaper-slow-generative-art/
    • ตอนนี้กำลังทำแบบนั้นเป๊ะ ๆ ด้วย จอ e-ink อยู่ น่าเสียดายที่ยัง build ส่วนที่เกี่ยวกับ XNNPACK ใน repo บน Pi Zero 2W ไม่ได้
    • ไอเดียดีนะ ทุก ๆ ราว 10 ชั่วโมง ให้มันสร้างภาพใหม่เองจากธีมที่ผู้ใช้ให้ไว้แล้วอัปเดตก็ได้
    • แต่ไม่ค่อยเป็นมิตรต่อสิ่งแวดล้อมเท่าไร
  • เป็นผลงานที่น่าทึ่ง แต่แน่นอนว่าการสร้างภาพใช้เวลานานมหาศาล ใน README ระบุว่า 11 ชั่วโมง

    • ใช่เลย ผมคงไม่ได้ต้องการหรือใช้ implementation นี้เอง แต่เทคนิคที่ใช้ในนี้น่าจะถูกนำไปใช้กับเครื่องมืออื่น ๆ ต่อไป และนั่นจะยอดเยี่ยมมาก
    • น่าจะน่าสนใจถ้าดูว่าเมื่อเทียบกับวิธีที่ล้ำหน้ากว่าแล้ว มันเทียบเท่ากันแค่ไหนในแง่ต้นทุนและพลังงาน
      เช่น เปรียบเทียบเวลา ต้นทุน ฮาร์ดแวร์ทั้งหมดที่ต้องใช้ และพลังงานสำหรับการสร้างภาพ 100 ภาพด้วย Pi Zero 2 จำนวน 100 เครื่อง ซึ่งไม่จำเป็นต้องเป็นรุ่น W ด้วยซ้ำ กับเครื่องอย่างพีซีระดับกลางทั่วไป
      เดาว่าพีซีน่าจะยังชนะอยู่
      Zero 2 ดูเหมือนถูกใช้เป็นโจทย์ท้าทายมากกว่าจะใช้งานจริง ดังนั้น Pi 4 หรือ 5 อาจเป็นจุดอ้างอิงที่ดีกว่า
    • ประเด็นสำคัญคือมันรันบน Raspberry Pi ได้ แถมยังเป็น Zero 2 ด้วย
  • น่าประทับใจ
    จริงแท้แล้ว ยุคที่แม้แต่หลอดไฟกับเครื่องปิ้งขนมปังก็มีสติปัญญาอันล้ำเลิศใกล้มาถึงแล้ว
    ผมติดตามสาขานี้มาหลายปี แต่ 10 ปีที่ผ่านมานั้นน่าทึ่งมาก
    เหตุผลที่พูดว่า “ที่ผ่านมา” ก็เพราะ การเร่งตัวในช่วง 6–18 เดือนล่าสุด นั้นอยู่คนละระดับโดยสิ้นเชิง
    ผมไม่ได้กังวลว่าอีก 2 ปีเราจะทำอะไรได้ แต่กังวลว่าความเร็วในการพัฒนาจะเร่งขึ้นอีกแค่ไหน และมันก็จะเร่งขึ้นอีก ซ้ำแล้วซ้ำเล่า

    • เครื่องปิ้งขนมปังที่รับพรอมป์แล้ว วาดภาพนั้นลงบนขนมปังปิ้ง นี่ดีนะ อาจเอาความร้อนจาก GPU มาใช้ปิ้งขนมปังจริงได้ด้วย
      มาตั้งสตาร์ทอัพกันเถอะ
  • ถึงจุดนี้ ความพยายามจะกำกับควบคุมเทคโนโลยีตระกูล Stable Diffusion ก็ถือว่าจบแล้วไม่ใช่หรือ? ถ้าสามารถย่อโมเดลและโครงสร้างพื้นฐานสำหรับ inference ลงจนถึงระดับที่ รันบน PS2 ได้ ก็ดูเหมือนจะเป็นไปไม่ได้ที่จะหยุดเทคโนโลยีนี้โดยไม่มีรัฐเฝ้าระวังแบบเผด็จการเบ็ดเสร็จ และแม้แต่รัฐแบบนั้นก็อาจทำได้แค่เฉียด ๆ เท่านั้น

    • สงครามกับคอมพิวติ้งอเนกประสงค์ ยังดำเนินอยู่ แต่ยังไม่ได้ลุกลามไปถึงขั้นห้ามไม่ให้ผู้คนเป็นเจ้าของอุปกรณ์คอมพิวติ้งอเนกประสงค์
    • ถ้าใช้ตรรกะนั้น การกำกับควบคุมการลักขโมยก็จบแล้วไม่ใช่หรือ? แค่มีร่างกายก็เปิดหน้าต่างได้โดยไม่ต้องใช้เครื่องมือแล้ว ดังนั้นก็เท่ากับว่าหยุดการลักขโมยไม่ได้หากไม่มีรัฐเฝ้าระวังแบบเผด็จการเบ็ดเสร็จ
      สื่อ “เถื่อน” หรือ ransomware ก็เหมือนกัน
      รัฐกำกับควบคุมสิ่งที่บังคับใช้ด้วยเทคโนโลยีล้วน ๆ ไม่ได้มานานแล้ว
    • ข้อกำหนดเดิมของโมเดลแบบนี้คือ RAM 16GB และหาซื้อได้ในราคาต่ำกว่า 20 ดอลลาร์ มันรันบน GPU ได้เร็วกว่ามาก และ GPU แบบนั้นก็ซื้อได้ต่ำกว่า 200 ดอลลาร์ คนธรรมดาหลายล้านคนมีทั้งสองอย่างอยู่แล้ว
    • PS2 มี RAM แค่ 32MB เท่านั้น PS3 ก็มีแค่ 256MB
      เข้าใจว่าเป็นตัวอย่างที่พูดเกินจริงแบบสนุก ๆ แต่ถ้าจะให้รันบน PS2 ได้ ต้องย่อให้เล็กกว่านี้อีกมาก
    • ผมนึกว่าความพยายามด้านกฎระเบียบส่วนใหญ่เน้นไปที่ การรันเพื่อเทรน ที่ใหญ่ขึ้นเรื่อย ๆ มากกว่าการใช้งานสร้างผลลัพธ์จากโมเดลที่มีอยู่ มีกฎระเบียบเฉพาะเกี่ยวกับการใช้โมเดลเองด้วยหรือ?
  • รอวันที่จะมี Stable Diffusion สำหรับ Windows 3.1 แทบไม่ไหวแล้ว

  • บ้าไปแล้ว ต่อให้ใช้เวลา 11 ชั่วโมงก็เถอะ ผมไม่เคยคาดคิดเลยว่า SD จะรันได้ บนฮาร์ดแวร์อย่าง Pi Zero