ประสิทธิภาพ AI ของ AI PC ยังไม่พอ: CPU แซง NPU
(github.com/usefulsensors)- ผลการรัน NPU benchmark บน SoC แบบ Arm ของ Qualcomm ใน Microsoft Surface Pro 11th Edition พบว่าค่าประมวลผลที่วัดได้ต่ำกว่าประสิทธิภาพเร่งความเร็วที่ Windows AI PC โฆษณาไว้อย่างมาก
- การทดสอบถูกจัดขึ้นโดยใช้ Onnx Runtime และตัวให้บริการการรัน Qualcomm QNN เพื่อรันงาน MatMul ขนาดใหญ่ ที่มีลักษณะใกล้เคียงกับเลเยอร์ที่กินต้นทุนสูงในโมเดลตระกูล transformer
- ในตัวอย่างผลลัพธ์ CPU ทำได้ 821 Gigaops/s, ส่วน NPU ทำได้ 225 Gigaops/s ในคอนฟิกแบบ quantization ที่มีอินพุต/เอาต์พุตเป็น float และ 573 Gigaops/s ในคอนฟิกที่ใช้อินพุต/เอาต์พุตแบบ 8-bit ด้วย
- ค่า 573 Gigaops/s ของ NPU คิดเป็นเพียง 1.3% ของตัวเลข 45 Teraops/s ในสื่อการตลาดของ Microsoft Surface Pro 11th Edition และเมื่อรันโมเดลเดียวกันบน Nvidia Geforce RTX 4080 Laptop GPU จะได้ 3.2ms หรือ 2,160 Gigaops/s
- ผลลัพธ์ปัจจุบันอ้างอิง ณ วันที่ 2 ตุลาคม 2024 และแม้ยังคาดหวังได้ว่าซอฟต์แวร์ เฟรมเวิร์ก และไดรเวอร์อาจช่วยลด latency ลงได้ในอนาคต แต่ใน benchmark นี้ CPU ยังเร็วกว่า NPU
จุดประสงค์ของ benchmark Qualcomm NPU บน Surface
- Microsoft ทำตลาด Surface แท็บเล็ตที่ใช้ SoC แบบ Arm ของ Qualcomm ในฐานะ AI PC บน Windows โดยโปรโมตว่าสามารถรันโมเดลแมชชีนเลิร์นนิงได้เร็วและมีประสิทธิภาพมากขึ้น
- Useful Sensors มองบวกต่อฮาร์ดแวร์ Qualcomm และ NPU และได้ลงเวลาและทรัพยากรเพื่อนำแอป third-party ของตนมา port ลงแพลตฟอร์มนี้
- เนื่องจากยังมีตัวอย่างโค้ดหรือ benchmark ไม่มากนักที่แสดงให้นักพัฒนาภายนอกเห็นว่าจะทำอย่างไรให้ได้ผลลัพธ์ที่เร็ว ผู้พัฒนาจึงเผยแพร่ประสิทธิภาพที่สังเกตได้จริงในรูปแบบโปรเจกต์อิสระขนาดเล็ก
- ประสิทธิภาพที่วัดได้ต่ำกว่าคาดมาก และแม้จะเคยเห็นฮาร์ดแวร์ชุดเดียวกันทำงานได้มีประสิทธิภาพบนแพลตฟอร์มอื่นอย่าง Android จึงยังเปิดไว้สำหรับความเป็นไปได้ที่จะปรับปรุงได้ผ่านการเปลี่ยนแปลงด้านแอปพลิเคชัน เฟรมเวิร์ก และไดรเวอร์ในอนาคต
สภาพแวดล้อมการรันและข้อจำกัดในการติดตั้ง
- การทดสอบใช้สคริปต์ Python บน Windows
- ณ วันที่ 2 ตุลาคม 2024 Python จาก Microsoft Store ยังไม่รองรับสถาปัตยกรรม Arm จึงไม่เหมาะกับการรันแพ็กเกจที่จำเป็นต่อการเข้าถึง Qualcomm NPU
- ในผลลัพธ์นี้ใช้ ไฟล์ติดตั้ง Python 3.11.9 Arm64
- ยังไม่มีแพ็กเกจ Onnx ที่ build ไว้ล่วงหน้าสำหรับ Windows on Arm จึงต้องใช้ CMake และคอมไพเลอร์ของ Visual Studio
- ติดตั้ง CMake ด้วย
winget install cmake - Visual Studio ใช้ Visual Studio Community Edition และเลือก workload
Desktop C++ Developmentตอนติดตั้ง
- ติดตั้ง CMake ด้วย
- ติดตั้งแพ็กเกจ Python ในโฟลเดอร์รีโพด้วย
py -m pip install -r requirements.txt- Onnx branch เป็นเวอร์ชันที่ backport การแก้ไขการคอมไพล์
pylauncher อย่างเป็นทางการลงใน Onnx 1.16 - Qualcomm Onnx Runtime ใช้คอมบิเนชันนี้เพราะ Onnx รุ่นใหม่กว่าจะขึ้นข้อผิดพลาด
Unsupported model IR version - แพ็กเกจ Qualcomm Onnx Runtime ใช้ nightly build
- Onnx branch เป็นเวอร์ชันที่ backport การแก้ไขการคอมไพล์
การรัน benchmark และการตีความผลลัพธ์
- รัน benchmark ด้วย
py benchmark_matmul.py - Onnx Runtime จะแสดง log จำนวนมากระหว่างการรันช่วงแรก
- ตัวอย่างเช่น จะมีข้อความจาก
cpuinfoว่าไม่รู้จักรุ่นชิปSnapdragon(R) X 12-core X1E80100 @ 3.40 GHz - ยังมี log ของขั้นตอนสรุปกราฟและขั้นตอนเสร็จสิ้นด้วย
- ตัวอย่างเช่น จะมีข้อความจาก
- ผล benchmark จริงจะแสดงตอนท้าย
NPU quantized compute, float I/O accuracy difference is 0.0100NPU quantized compute and I/O accuracy difference is 0.0060CPU took 8.42ms, 821,141,860,688 ops per secondNPU (quantized compute, float I/O) took 30.63ms, 225,667,671,183 ops per secondNPU (quantized compute and I/O) took 12.05ms, 573,475,650,364 ops per second
- สองบรรทัดแรกแสดง ค่าความต่างด้านความแม่นยำ เพื่อตรวจว่าผลลัพธ์เชิงตัวเลขของ CPU และ NPU สอดคล้องกันหรือไม่
- สามบรรทัดสุดท้ายแสดงเวลาแบบ wall-clock ของการรันโมเดลตั้งแต่ต้นจนจบ และปริมาณงานต่อวินาทีที่คำนวณจาก latency นั้น
โมเดลที่ใช้วัดและวิธี quantization
- benchmark นี้ถูกออกแบบมาเพื่อจำลอง การคูณเมทริกซ์ขนาดใหญ่ 6 ชุด ที่คล้ายกับเลเยอร์ซึ่งใช้เวลามากในโมเดล transformer อย่าง OpenAI Whisper
- รูปร่างอินพุตคือ
(6, 1500, 256) X (6, 256, 1500) - รูปร่างผลลัพธ์คือ
(6, 1500, 1500) - โมเดลประกอบด้วยโหนด
MatMulเดียว โดยมีอินพุต 2 ตัวและเอาต์พุต 1 ตัว
- รูปร่างอินพุตคือ
- โมเดลถูกสร้างขึ้นแบบ on-the-fly ด้วยเฟรมเวิร์กโมเดล Onnx แล้วส่งต่อให้ Onnx Runtime
- โมเดลอ้างอิงเป็นเวอร์ชัน float ล้วน และรันบน CPU เท่านั้น
- หากต้องการให้ NPU รันได้อย่างมีประสิทธิภาพ โดยมากจำเป็นต้องใช้ โมเดลแบบ quantized และ float16 รองรับอย่างจำกัด
- แนวทางแรกสำหรับ NPU ใช้เมธอด ORT ทางการ
quantize_static()- เพื่อความสะดวก เทนเซอร์อินพุตและเอาต์พุตยังคงเป็น 32-bit float
- มีการแปลงค่าที่ต้นและท้ายกราฟตอนรันไทม์ และให้ส่วนคำนวณที่เหลือรันแบบ 8-bit
- ในคอนฟิกนี้ งานแปลงค่าของ NPU ช้ามาก และใน
npu_quant_profile.csvส่วนแปลงค่ากินเวลามากกว่า 75% ของเวลาทั้งหมด - แนวทางที่สองคือสร้างกราฟโมเดลที่เทียบเท่ากันโดยโปรแกรม โดยใช้อินพุตและเอาต์พุตแบบ 8-bit
- วิธี
quantized compute and I/Oนี้มักเร็วกว่าเวอร์ชัน float I/O ราว 3 เท่า - จากการ profiling เวลาส่วนใหญ่ถูกใช้ไปกับการคูณเมทริกซ์ตามที่คาดไว้
- วิธี
ตัวแปรที่นำมาพิจารณาในการวัดประสิทธิภาพ
- มีการพิจารณาว่าเป็นงานแบบ compute bound หรือไม่ โดยเลือก shape ของเมทริกซ์ให้ใกล้เคียงสี่เหลี่ยมมากขึ้น
- โมเดล transformer สมัยใหม่ต่างจากโมเดล convolution รุ่นเก่าตรงที่อาศัยการคูณเมทริกซ์ขนาดใหญ่
- หากเลเยอร์มีลักษณะใกล้กับการคูณเมทริกซ์-เวกเตอร์มากขึ้น การนำ weight กลับมาใช้ซ้ำจะลดลง และการดึงค่าจาก DRAM อาจกลายเป็นคอขวด
- มิติ
kของเมทริกซ์เดิมใน tiny Whisper คือ 64 แต่ benchmark นี้เพิ่มเป็น 256 เพื่อเปิดพื้นที่ให้มีการปรับแต่ง SIMD มากขึ้น
- การตั้งค่าพลังงานถูกปรับไปทางเพิ่มประสิทธิภาพ
- พยายามตั้งค่า Windows energy ทั้งหมดเป็น
Best Performance - รัน benchmark ขณะเสียบไฟกับแท็บเล็ต
- ตัวเลือกเซสชัน
htp_performance_modeของ Qualcomm Onnx Runtime ถูกตั้งเป็นsustained_high_performanceเพราะให้ latency รวมต่ำที่สุดในการทดลอง
- พยายามตั้งค่า Windows energy ทั้งหมดเป็น
- โครงสร้างโมเดลถูกจำกัดให้เป็นการคูณเมทริกซ์เดี่ยวเพื่อให้ตีความได้ง่าย
- แม้จะทำหลายเลเยอร์, convolution หรือ weight แบบ static ได้ แต่เลือก MatMul เดี่ยวที่มีอินพุตแบบ dynamic เพื่อสะท้อนโครงสร้าง transformer ที่ใช้กันแพร่หลายใน LLM และโมเดลสมัยใหม่
- ยังมีความเป็นไปได้ของความผิดพลาดในการตั้งค่า
- ใช้ unsigned 8-bit quantization และองค์ประกอบ
qdqภายในกราฟ - แม้จะพยายามทำตามแนวปฏิบัติที่ดีในเอกสาร แต่อาจยังหลุดจาก fast path ของไดรเวอร์หรือการทำงานของตัวเร่ง
- ใช้ unsigned 8-bit quantization และองค์ประกอบ
- ยังมีการพิจารณาตัวเลือก API สำหรับเข้าถึง AI acceleration บน Windows
- ดูเหมือน DirectML จะรองรับเฉพาะการเข้าถึง GPU
- ดูเหมือน OpenVino จะไม่สามารถรันบนฮาร์ดแวร์ Arm นี้ได้
- การใช้ Qualcomm QNN SDK โดยตรงก็ให้ผลประสิทธิภาพใกล้เคียงกัน
- TensorFlow Lite ไม่รองรับ Windows for Arm
- จากการสำรวจและทดลองนี้ Onnx ดูเป็นเฟรมเวิร์กที่เหมาะที่สุดสำหรับการได้ประสิทธิภาพเร่งด้วย NPU เพราะได้รับการสนับสนุนทั้งจาก Microsoft และ Qualcomm
การตีความผลลัพธ์
- ผลลัพธ์นี้อ้างอิง ณ วันที่ 2 ตุลาคม 2024 และวัดบน Microsoft Surface Pro 11th Edition
- SoC คือ
Snapdragon(R) X 12-core X1E80100 @ 3.40 GHz
- SoC คือ
- แม้ตัดงานแปลง float ออกแล้ว ผลของ NPU ก็ยังช้ากว่า CPU
- ในมุมมองของ accelerator ถือว่าไม่ใช่ผลลัพธ์ที่น่าพอใจ
- อย่างไรก็ตาม ยังไม่ตัดความเป็นไปได้ว่ามันอาจมีข้อดีด้านประสิทธิภาพพลังงานหรือ sustained performance
- ค่าประสิทธิภาพสูงสุดของ NPU ที่วัดได้คือ 573 billion ops/s ซึ่งเท่ากับ 1.3% ของตัวเลข 45 trillion ops/s ในสื่อการตลาดของ Microsoft Surface Pro 11th Edition
- เมื่อรันโมเดลเดียวกันบน Nvidia Geforce RTX 4080 Laptop GPU ใช้เวลา 3.2ms
- คิดเป็น 2,160 billion ops/s
- สูงกว่าค่าที่วัดได้จาก NPU บน Surface เกือบ 4 เท่า
2 ความคิดเห็น
ผมเข้าใจมาตลอดว่า npu ของ ryzen เร็วกว่า cpu อยู่เล็กน้อย แต่พอเห็นแบบนี้แล้วความอยากได้ Snapdragon ลดฮวบเลย
ความคิดเห็นจาก Hacker News
ดูจากผลแล้ว โดยรวมเหมือนว่า การใช้ทรัพยากรประมวลผล ยังทำได้ไม่ดีนัก CPU 8.4ms, GPU 3.2ms ต่างกันน้อยเกินไป และในกรณีนี้น่าจะคาดหวังความต่างระดับ 10–20 เท่าได้
สาเหตุอาจเป็น onnxruntime ก็ได้ ดูเหมือนมีผู้ผลิตฮาร์ดแวร์บางรายที่ปล่อยแค่หน่วยประมวลผลออกมา แต่การสนับสนุนที่ดีจริง ๆ ยังไม่ตามมา ต้องรอดูว่าจะเปลี่ยนได้เร็วแค่ไหน
อีกอย่าง หลายคนมักเข้าใจผิดว่าเป้าหมายของ NPU คือ “ความเร็ว” แต่แก่นจริง ๆ คือ ใช้พลังงานต่ำ ถ้าจะเน้นความเร็ว ต้องกำจัดคอขวดหน่วยความจำ และสุดท้ายก็จะไปออกแบบ ASIC ที่มีหน่วยความจำของตัวเอง NPU ในอุปกรณ์ส่วนใหญ่ติดอยู่กับ SoC รอบ ๆ CPU เพื่อใช้ offload งานประมวลผล AI
ถ้ารันเบนช์มาร์กนี้แบบลูปไม่สิ้นสุดบนอุปกรณ์ทั้งสามคือ CPU/NPU/GPU แล้ววัดการใช้พลังงาน น่าจะน่าสนใจ คาดว่า NPU จะต่ำที่สุดและมีจำนวนการคำนวณต่อวัตต์ดีที่สุดด้วย
เช่น ในฟิลเตอร์ภาพถ่าย AI นั้น GPU อาจกำลังเรนเดอร์พรีวิว ส่วน CPU ก็น่าจะยุ่งกับ UI และการรับอินพุตจากผู้ใช้
Apple Accelerate เคยเป็นเส้นทางแทบจะ唯一เดียวในการเข้าถึงหน่วยเมทริกซ์ของ CPU ก่อน M4 และ NPU ถ้าอยากใช้อย่างอื่น ก็ต้องเตรียมส่งแพตช์ให้เฟรมเวิร์กแมชชีนเลิร์นนิงที่เลือก หรือเตรียมเขียนโค้ดฝึกและ inference เอง
สุดท้าย Python ก็เรียก C อยู่ดี แต่ก็น่าสนใจมากว่าประสิทธิภาพหายไปมากแค่ไหน
ถ้าใช้ GPU ต้องพิจารณาด้วยว่าในเวลาที่วัดนั้นรวม งานแบบ asynchronous หรือไม่
ถ้าใช้
time.time()แบบซื่อ ๆ CPU ก็แค่บันทึกเวลา ส่วนmodel(input.cuda()).cuda()จะส่งข้อมูลไปยังหน่วยความจำ GPU และเริ่มคำนวณ แต่เพราะเป็น asynchronous เวลาสิ้นสุดจึงอาจถูกบันทึกโดยไม่เกี่ยวว่าผลลัพธ์พร้อมจริงหรือยังเป็นพฤติกรรมที่คาดเดายากถ้าไม่รู้จักระบบและฮาร์ดแวร์ ไม่ใช่แค่ Python เท่านั้น ภาษาแทบทั้งหมดถูกออกแบบให้คอมไพล์ออกมาในรูปแบบที่เหมาะสมกว่าตัวโค้ดที่เขียน และเมื่อไม่มีการล็อกก็จะไม่บล็อกงานของ CPU
ถ้าจะวัดงาน GPU จริง ๆ ต้องดู CUDA event timer ใน PyTorch ใช้วิธี
torch.cuda.Event(enable_timing=True)นอกจากนี้ ขนาดและรูปแบบหน่วยความจำก็ซับซ้อน เบนช์มาร์กนี้ใช้รูปแบบที่ไม่เป็นผลดีกับ NPU โดยปกติ NPU และ GPU ต้องการ channels last ดังนั้น
[1,1500,1500,6]จึงถูกกว่า[1,6,1500,1500]ตัวเลข 1500 กับ 6 ก็เป็นเลขแปลก ๆ ไม่ดีต่อ NPU และเมื่อคิดว่าอุปกรณ์แบบนี้ยังใหม่อยู่ การสูญเสียประสิทธิภาพอาจค่อนข้างมาก
รายละเอียดเพิ่มเติมเขียนไว้ที่ https://news.ycombinator.com/item?id=41864828
NPU เหล่านี้กิน พื้นที่ซิลิคอน ไปไม่น้อย ถ้าท้ายที่สุดแทบไม่ได้ใช้งานก็คงน่าเสียดายจริง ๆ ผมหาการวิเคราะห์ไดที่แยกเฉพาะ NPU ออกจาก Snapdragon X ไม่เจอ แต่ฝั่ง AMD ที่มีเป้าหมายคล้ายกันประมาณ 50 TOPS ดูได้ที่นี่ และมันกินพื้นที่ประมาณเท่าคอร์ CPU ประสิทธิภาพสูง 3 คอร์
https://www.techpowerup.com/325035/amd-strix-point-silicon-p...
ที่แย่กว่านั้นคือดูเหมือนคนส่วนใหญ่ก็ไม่ได้ต้องการเหมือนกัน และผลสำรวจล่าสุดบางส่วนก็แสดงให้เห็นว่าความไม่พอใจต่อการแทรกซึมของ AI มีมากกว่า ไม่ควรต้องจ่ายเงินเพิ่มให้ของแบบนี้ และควรเป็นตัวเลือกเท่านั้น
ถ้าทำแบบนั้น ยอดขายจะแสดงให้เห็นว่ามีคนอยากจ่ายพรีเมียมให้ “AI” น้อยแค่ไหน และจะทำให้ชัดเจนว่ามันถูกโหมเกินจริงและไม่จำเป็นเพียงใด
ดังนั้นเป้าหมายของชิ้นส่วนแบบนี้คือให้ถูกใช้งาน แต่ไม่ถูกใช้งานมากเกินไป
แทนที่จะเป็น NPU อาจเอาทรานซิสเตอร์และพื้นที่ไดนั้นไปใช้ได้หลายอย่าง แต่คงไม่ได้ใส่คอร์ CPU ประสิทธิภาพสูงเพิ่ม เพราะจะทำให้ความหนาแน่นพลังงานสูงเกินไป เกิดปัญหาความร้อนที่แก้ยากถ้าไม่มีการ throttling ถาวร
[1] https://en.wikipedia.org/wiki/Dark_silicon
สำหรับคนที่ไม่รันโมเดล มันดูเหมือนเป็นการสิ้นเปลือง และผมก็สงสัยว่ามีวิธีเอาไปใช้ประโยชน์อย่างอื่นได้อย่างไรบ้าง
ซอฟต์แวร์สำหรับผู้บริโภคไม่ได้สเกลไปถึงระดับนั้นอยู่แล้ว เลยสงสัยว่าจะเอาทรานซิสเตอร์ไปจัดสรรให้ CPU เพิ่มแล้วทำอะไรได้
คล้ายกับเหตุผลที่ Apple ใส่วิดีโอเอนจินจำนวนมากใน SoC ด้วยงบทรานซิสเตอร์ที่รับได้ ก็ไม่ได้มีที่อื่นให้เอาไปใช้มากนัก การเพิ่มประสิทธิภาพ single-thread ไม่ได้ถูกจำกัดด้วยจำนวนทรานซิสเตอร์อย่างเดียวอีกต่อไป และซอฟต์แวร์ก็ทำ multithreading ได้ไม่ดี
ผมเคยคิดว่าจุดประสงค์ของอุปกรณ์แบบนี้ไม่ใช่ความเร็ว แต่คือการรัน โมเดลขนาดเล็กด้วยพลังงานต่ำมาก ผมใช้โน้ตบุ๊ก AMD รุ่นใหม่ที่มี NPU อยู่ พอเปิดเอฟเฟกต์วิดีโอที่บอกว่ารันบน NPU การใช้พลังงานไม่เปลี่ยน แต่ถ้าใช้ Nvidia Studio Effects การใช้พลังงานจะเพิ่มขึ้น
NPU ดูเหมือนจะมีไว้สำหรับโมเดลที่ปรับแต่งมาอย่างมากเพื่อทำงานเล็ก ๆ เช่น การสบตา เบลอพื้นหลัง โมเดลแก้ไขอัตโนมัติ การถอดเสียง และ OCR โดยเฉพาะบน Windows ผมเข้าใจว่ามันรัน OCR ทั้งหน้าจอและ embedding สำหรับการค้นหาเพื่อใช้กับฟีเจอร์ rewind
ช่วงนี้ AMD ทำงานได้ยอดเยี่ยม แต่ดูเหมือนจะไม่ได้โฆษณาเสียงดังนัก อันนี้น่าสนใจเป็นพิเศษ: https://lore.kernel.org/lkml/DM6PR12MB3993D5ECA50B27682AEBE1...
แก้ไข: มันไม่ใช่ FPGA วันนี้เพิ่งได้รู้
ลองประเมินโมเดล CoreML บน macOS ก็จะเห็นได้ ANE ใช้เวลาประมาณครึ่งหนึ่งของ GPU และ GPU ใช้เวลาประมาณครึ่งหนึ่งของ CPU อัตราส่วนจริงขึ้นอยู่กับโมเดล
ชิปที่จะคุกคาม Nvidia น่าจะเป็นชิปและหน่วยความจำที่ราคาถูกพอจะรันโมเดลที่ดีพอใช้บนอุปกรณ์ส่วนบุคคลอย่างสมาร์ตโฟนได้
หากคนทั่วไปเห็นพ้องว่า LLM มีประโยชน์ และยอมจ่ายพรีเมียมเพิ่มเล็กน้อยกับราคาอุปกรณ์ ผมคิดว่าอนาคตของเทคโนโลยีนี้โดยแก่นแล้วคือโมเดลส่วนบุคคลที่ให้ความเป็นส่วนตัวในตัวเอง
ปริมาณข้อมูลส่วนตัวที่ผู้คนเทลงไปในที่อย่าง ChatGPT นั้นน่าตกใจมาก ดูใน Reddit จะเห็นว่าผู้ที่ติดแอปแฟนสาวเสมือน AI มักส่งต่อรสนิยมที่มืดที่สุด คำสารภาพที่เปราะบาง และแม้แต่บทสนทนาที่อาจเข้าข่ายอาชญากรรมให้บริษัทแอปนิรนาม
Google เองก็ระบุชัดเจนว่าหากเปิดประวัติ Gemini ไว้ ก็อาจมีการตรวจสอบเนื้อหาการสนทนาได้
การทำนายโทเค็นที่ซับซ้อนซึ่งต้องใช้โมเดลใหญ่กว่าอาจถาม LLM บนคลาวด์ได้ แต่สำหรับผู้บริโภค ความเป็นส่วนตัวต้องได้รับการรับประกันอย่างแน่นอน
ผมไม่คิดว่าผู้ช่วยส่วนตัวทั่วไป การแชต และการค้นหาข้อมูลในชีวิตประจำวันจำเป็นต้องใช้การอนุมานระดับล้ำสุดหรือ LLM แบบโชว์ความสามารถพิเศษ
อย่างไรก็ตาม ข้อสรุปเฉพาะในบทความยังน่าสงสัยอยู่บ้าง มันเป็น ONNX ของ Qualcomm และอาจเก่าแล้ว ฝั่ง Android มักบ่นกันมากเรื่องวิศวกรรมซอฟต์แวร์ของ Qualcomm
แต่ทิศทางนั้นถูกต้อง คำกล่าวอ้างเรื่องการเร่ง AI ในฮาร์ดแวร์ผู้บริโภคส่วนใหญ่แทบจะเป็นการคุยโวโดยทั่วไป ข้อยกเว้นคือ A) ใช้ซอฟต์แวร์ 1P หรือ B) มีใครบางคนภายใน 1P ที่อยากให้คุณใช้ฟีเจอร์นั้นจริง ๆ
แม้ใช้ของอย่าง TensorRT ก็ไม่น่าจะเร็วเท่าการเขียนเองตั้งแต่ต้น และนี่ก็เป็นเหตุผลที่ Nvidia ทุ่มกำลังคนจำนวนมาก แต่ก็เข้าใกล้ได้พอสมควรและลดเวลาเขียนลงได้มาก
อุปกรณ์แบบนี้โดยทั่วไปถูกปรับแต่งมาสำหรับงานที่คล้าย ๆ กันและทำซ้ำ ๆ ดังนั้นผมคิดว่าข้อมูลบางส่วนที่เก็บมาจากตรงนี้อาจไม่ถูกต้อง
ผมยังไม่เคยใช้งานชิป NPU เหล่านี้โดยตรง แต่ยากจะเชื่อถือ timing ได้ timing ของ CUDA ช่วงท้ายมีโอกาสสูงที่วัดไม่ถูกต้องตามโค้ด การวัด timing ไม่ง่ายอย่างที่คิด
จำนวนการคำนวณที่โฆษณาไว้นับเฉพาะการคำนวณที่ทำบน NPU โดยตรง ขณะที่ต้นฉบับอาจรวมงาน CPU เข้าไปในการวัด NPU และ GPU ด้วย เอกสารมีเครื่องมือ benchmark อยู่ จึงน่าจะใช้แนวทางใกล้เคียงกัน และผมก็อยากรู้ว่าหลัง warm-up แล้ว variance เป็นอย่างไร
รูปแบบข้อมูลก็ดูเหมือนจะผิดด้วย ที่นี่ต้องใช้
channels lastเอกสารก็ยืนยันเรื่องนี้ตัวเลข 1500 ก็ดูแปลก จึงอาจเกิดความผิดพลาดเพิ่มเติมได้ ผลลัพธ์อาจต่างออกไปเมื่อเป็น 1536, 2048, 256 หรือค่าที่เล็กกว่านั้น โมเดลจริงไม่ได้ประมวลผลภาพเต็มความละเอียด และหากปรับสถาปัตยกรรมให้เหมาะกับโมเดล ข้อมูลเรื่อง shape จะสำคัญ ในแมชชีนเลิร์นนิง การปรับแต่ง shape ค่อนข้างสำคัญ
ดูเอกสารแบบเร็ว ๆ แล้ว การตั้งค่าก็ดูไม่เหมาะสม “Model Workflow” บอกว่าต้องการข้อมูลเป็นเลขทศนิยม 8 บิตหรือ 16 บิต แต่เลขทศนิยมก็มีหลายชนิด bfloat ของ PyTorch ไม่เหมือนกับ
torch.halfหรือtorch.float16mixed precision ยังเป็นหัวข้อที่ชวนสับสนอยู่ ดังนั้นหากมีปัญหาแบบนี้ก็ควรตรวจดูให้ดี ไม่แนะนำให้รันแค่ขั้นตอน quantization มาตรฐานแล้วจบ แค่ใช้เป็นจุดเริ่มต้นได้ แต่ถ้ายังไม่ “ดีพอ” ก็ไม่ควรหยุดแค่นั้น
ถึงอย่างนั้นผมไม่ได้คิดว่าผลลัพธ์นี้ไร้ประโยชน์ เพียงแต่ต้องปรับปรุง เรื่องแบบนี้ซับซ้อนกว่าที่คิด และส่วนใหญ่เป็นเพราะเทคโนโลยียังใหม่ รายละเอียดยังอยู่ระหว่างการจัดระเบียบ
เมื่อเทียบกับ CPU หรือ GPU โดยเฉพาะ CUDA ควรจำไว้ว่ามีการทุ่มแรงงานระดับหลายแสนคน-ชั่วโมง และแม้แต่ไลบรารีระดับสูงอย่าง Python ก็มีอย่างน้อยหลายหมื่นคน-ชั่วโมง อุปกรณ์เหล่านี้ยังไม่พร้อมนักสำหรับการใช้งานโดยตรงในระดับ abstraction ของภาษาที่ผู้ใช้ทั่วไปชอบ แต่ถ้ายอมทำงานใกล้กับฮาร์ดแวร์มากขึ้น ก็มีประโยชน์ไม่น้อย
หากจะวัดงาน GPU แบบ asynchronous ใน PyTorch ควรใช้ CUDA events และ
torch.cuda.synchronize()แทนการเอา CPU timer ไปคร่อม output ของโมเดล[1] https://www.thonking.ai/p/what-shapes-do-matrix-multiplicati...
การนำโมเดลไปปรับใช้บน NPU ต้องอาศัย การปรับแต่งตามโปรไฟล์ ค่อนข้างมาก หากเอาโมเดลที่รันบน CPU ได้ดีมาใช้โดยไม่ปรับแต่งสำหรับ NPU ผลลัพธ์มักน่าผิดหวัง
คำอธิบายในรีโพสitory GitHub ให้ข้อมูลมีประโยชน์กว่าบล็อกมาก
ถ้ารันการคูณเมทริกซ์ int8 ด้วย onnx ประสิทธิภาพอยู่ที่ประมาณ 0.6TF
https://github.com/usefulsensors/qc_npu_benchmark
บอกว่าทำให้เมทริกซ์อินพุตใกล้เคียงสี่เหลี่ยมจัตุรัสมากขึ้นเพื่อให้ทำ tiling และ reuse ได้ แต่ก็ไม่น่าแปลกใจหากการปรับแต่งที่เป็นไปได้จำนวนมากไม่ได้เข้าไปอยู่ใน Onnx
ดูเหมือน Qualcomm จะไม่เปิดให้เข้าถึง NPU โดยตรง แต่คาดหวังให้ผู้ใช้แปลงโมเดลผ่านเฟรมเวิร์กแล้วส่งต่อเข้าไป จากประสบการณ์ของผม เครื่องมือแปลงมักไม่ค่อยดีนักและพลาดการปรับแต่งไปมาก
ดังนั้นอาจไม่ใช่ “NPU ไม่ดี” แต่เป็น “เครื่องมือแปลงไม่ดี” มากกว่า ผมจะรอจนกว่าจะเข้าถึงได้โดยตรง และไม่ไว้ใจเครื่องมือแปลง
ผมมองว่า NPU เหมาะกับโมเดลแมชชีนเลิร์นนิงขนาดเล็กมาก ๆ และการประมาณฟังก์ชันที่เร็วมาก นั่นคือการใช้งานที่ผมตั้งใจไว้ ถึง LLM จะกำลังมาแรง แต่มีงานเฉพาะทางจำนวนมหาศาลที่โมเดลเล็กมีประโยชน์จริง ๆ
ไม่ได้หมายความว่าไม่มีของแบบนั้น แต่พูดตรง ๆ คือผมไม่ค่อยรู้ว่ามันคืออะไร เลยอยากทราบ
หวังว่า NPU ของ Elite X จะเข้าถึงได้ง่ายขึ้นเพราะ Copilot+ แต่ประเด็นคือมันไม่มีทางง่ายแบบ “รันโมเดลทั่วไปแล้วมันจะเทเลพอร์ตไป NPU อย่างมหัศจรรย์” แน่นอน
RTX 4080 น่าจะทำได้ประมาณ 40 TFLOPS แต่ในนี้รายงานแค่ 216,000 ล้านการดำเนินการต่อวินาที ระดับนี้ทำให้คิดว่าควรตรวจสอบเบนช์มาร์กใหม่
เป็นไปได้สูงว่ามีข้อผิดพลาดร้ายแรงในการวัด FLOPS การที่ CPU ชนะ NPU เป็นเรื่องที่เป็นไปได้ แต่ถ้าจะเปรียบเทียบให้ถูกต้อง ควรเบนช์มาร์กการคูณเมทริกซ์หลายชุดโดยไม่มีการซิงโครไนซ์แอปพลิเคชัน
เบนช์มาร์กเป็น การคูณเมทริกซ์ รูปแบบ
(6, 1500, 256) X (6, 256, 1500)ซึ่งในโลก AI ไม่ได้ใหญ่เท่าไร หากเป็นเมทริกซ์ที่ใหญ่กว่านี้มาก ช่องว่างก็น่าจะยิ่งกว้างขึ้นตัวอย่างเช่น แม้แต่หนึ่งในโมเดลขนาดเล็กอย่าง Llama 3.1 8B ก็มีการคูณเมทริกซ์แบบ
(batch, 14336, 4096) x (batch, 4096, 14336)ผมมองว่าเบนช์มาร์กนี้ยังไม่สมจริงพอ
ผมลองรัน qprof ซึ่งเป็นโปรไฟเลอร์ NPU ของ Qualcomm กับเบนช์มาร์กนี้แล้ว จากผลโปรไฟล์ งานถูกแจกไปยังเวกเตอร์คอร์ ไม่ใช่เทนเซอร์คอร์ที่ให้พลังประมวลผลส่วนใหญ่ของ NPU
คำนวณคร่าว ๆ แล้ว HMX ดูจะแรงกว่า HVX 30 เท่า
ภาระงานค่อนข้างเล็ก จึงใช้ความสามารถของฮาร์ดแวร์ได้ไม่เต็มที่เพราะโอเวอร์เฮดของการทำ quantization/dequantization อินพุต/เอาต์พุต และการแมป NCHW-NHCW การ padding น้ำหนักและอินพุตให้เป็นพหุคูณของ 64 ก็น่าจะช่วยประสิทธิภาพได้เช่นกัน
กราฟโปรไฟล์: https://imgur.com/a/2OKR93e
ประสิทธิภาพการคำนวณ HVX โดยประมาณคือ
4 * 2 * 1.43 * 1024 / 8 = 1.46TOPSที่ int8 โดย 4 คือจำนวนเวกเตอร์คอร์, 2 คือจำนวนการดำเนินการต่อไซเคิล, 1.43GHz คือความถี่ HVX, 1024bit คือความกว้างของเวกเตอร์รีจิสเตอร์ และ 8bit คือความละเอียด4 * 2 * 1.43 * 1024 / 8ชื่อบทความจริง ๆ ควรเป็น “Benchmarking Qualcomm's NPU on the Microsoft Surface Tablet”
นี่ไม่ใช่บทความเกี่ยวกับ NPU โดยทั่วไป แต่เป็นการดู NPU รุ่นหนึ่งด้วยเบนช์มาร์กเฉพาะและชุดไลบรารี/เฟรมเวิร์กเฉพาะ ดังนั้นในทางปฏิบัติจึงพิสูจน์อะไรไม่ได้เลย