กลับสู่คอร์สเรียน
AI032 Professional

การเขียนโปรแกรมโปรเซสเซอร์แบบขนานขนาดใหญ่: แนวทางปฏิบัติจริง

หลักสูตรนี้ให้การแนะนำอย่างละเอียดเกี่ยวกับการคำนวณบนหน่วยประมวลผลกราฟิก (GPU) และการเขียนโปรแกรมแบบขนานโดยใช้สภาพแวดล้อม CUDA C ครอบคลุมสถาปัตยกรรม GPU การประมวลผลแบบขนานของข้อมูล การจัดการเธรด การปรับปรุงหน่วยความจำ และประเด็นเรื่องประสิทธิภาพขั้นสูง พร้อมยกตัวอย่างกรณีศึกษาจริง เช่น การสร้างภาพจากการถ่ายภาพด้วยแม่เหล็กไฟฟ้า (MRI) และการมองเห็นโมเลกุล

4.9
36.0h
569 ผู้เรียน
0 การถูกใจ
ปัญญาประดิษฐ์
เริ่มเรียน

ภาพรวมคอร์สเรียน

📚 สรุปเนื้อหา

หลักสูตรนี้ให้การแนะนำอย่างละเอียดเกี่ยวกับการประมวลผลบนหน่วยประมวลผลกราฟิก (GPU) และการเขียนโปรแกรมแบบขนานโดยใช้สภาพแวดล้อม CUDA C โดยครอบคลุมสถาปัตยกรรม GPU การทำงานแบบขนานข้อมูล การจัดการเธรด การปรับปรุงหน่วยความจำ และประเด็นเรื่องประสิทธิภาพขั้นสูง พร้อมยกตัวอย่างกรณีศึกษาจริง เช่น การกู้คืนภาพ MRI และการมองเห็นโมเลกุล

เชี่ยวชาญศิลปะของการประมวลผลขนานที่มีประสิทธิภาพสูง ด้วยแนวทางปฏิบัติจริงในการใช้ CUDA และสถาปัตยกรรม GPU

ผู้แต่ง: David B. Kirk, Wen-mei W. Hwu

ขอบคุณ: Ian Buck, John Nickolls, ทีม NVIDIA DevTech, Jensen Huang, David Luebke, Bill Bean, Simon Green, Mark Harris, Manju Hedge, Nadeem Mohammad, Brent Oster, Peter Shirley, Eric Young, และ Cyril Zeller

🎯 เป้าหมายการเรียนรู้

  1. แยกแยะปรัชญาการออกแบบและแนวโน้มประสิทธิภาพระหว่างโปรเซสเซอร์หลายคอร์ (multicore CPU) และโปรเซสเซอร์หลายหน่วย (many-core GPU)
  2. ระบุองค์ประกอบหลักของสถาปัตยกรรม GPU สมัยใหม่ รวมถึง Streaming Multiprocessors (SMs) และโครงสร้างหน่วยความจำ
  3. ประยุกต์ใช้กฎของ Amdahl เพื่อคำนวณความเร็วที่เป็นไปได้ทางทฤษฎี และระบุผลกระทบจากจุดที่ทำให้เกิดความล่าช้าในส่วนลำดับ
  4. เปรียบเทียบ ความแตกต่างทางสถาปัตยกรรมระหว่างเส้นทางการทำงานแบบคงที่ (fixed-function pipelines) กับอาร์เรย์โปรเซสเซอร์ที่สามารถเขียนโปรแกรมได้ (programmable unified processor arrays)
  5. อธิบาย บทบาทของ "GPGPU" เป็นขั้นตอนกลาง และข้อจำกัดของโมเดลการเขียนโปรแกรมชูดิโอ (shader programming) แบบดั้งเดิม
  6. วิเคราะห์ ว่าฟีเจอร์ฮาร์ดแวร์เช่น การดำเนินการแบบอะตอม (atomic operations), การซิงโครไนซ์แบบบาร์เรียร์ (barrier synchronization), และการรองรับเลขทศนิยมสองตำแหน่ง (double-precision support) สนับสนุนการเปลี่ยนผ่านสู่การประมวลผลทั่วไปที่ขยายขนาดได้
  7. ระบุและใช้ประโยชน์จากความขนานข้อมูลภายในอัลกอริธึมการคูณเมทริกซ์กับเมทริกซ์
  8. นำเสนอบริหารหน่วยความจำบนอุปกรณ์ (device memory management) รวมถึงการจัดสรร การถ่ายโอนข้อมูลระหว่างโฮสต์กับอุปกรณ์ และการปล่อยหน่วยความจำกลับ
  9. สร้างและเริ่มต้นเคอร์เนลใน CUDA โดยใช้การดัชนีเธรดและการกำหนดโครงสร้างกริด/บล็อกที่เหมาะสม
  10. ออกแบบ โครงสร้างระดับเธรดแบบหลายมิติ (กริดและบล็อก) เพื่อจับคู่โครงสร้างข้อมูลที่ซับซ้อนเข้ากับฮาร์ดแวร์ GPU

🔹 บทเรียนที่ 1: บทนำสู่การประมวลผลแบบขนานและสถาปัตยกรรม GPU

บทสรุป: บทเรียนนี้สำรวจการเปลี่ยนแปลงพื้นฐานจากกระบวนการแบบลำดับเป็นแบบขนาน ซึ่งเกิดจากการที่ปรัชญาการออกแบบของโปรเซสเซอร์ (CPU) และหน่วยประมวลผลกราฟิก (GPU) แตกต่างกัน นักเรียนจะศึกษาแนวโน้ม “หลายคอร์” เทียบกับ “หลายหน่วย” ทำความเข้าใจสถาปัตยกรรมฮาร์ดแวร์ที่ทำให้ GPU สามารถประมวลผลได้ในปริมาณมาก และเรียนรู้ข้อจำกัดทางคณิตศาสตร์ของความเร็วโดยใช้กฎของ Amdahl

ผลลัพธ์การเรียนรู้:

  • แยกแยะปรัชญาการออกแบบและแนวโน้มประสิทธิภาพระหว่างโปรเซสเซอร์หลายคอร์ (multicore CPU) และโปรเซสเซอร์หลายหน่วย (many-core GPU)
  • ระบุองค์ประกอบหลักของสถาปัตยกรรม GPU สมัยใหม่ รวมถึง Streaming Multiprocessors (SMs) และโครงสร้างหน่วยความจำ
  • ประยุกต์ใช้กฎของ Amdahl เพื่อคำนวณความเร็วที่เป็นไปได้ทางทฤษฎี และระบุผลกระทบจากจุดที่ทำให้เกิดความล่าช้าในส่วนลำดับ

🔹 บทเรียนที่ 2: การพัฒนาและอนาคตของเทคโนโลยีการประมวลผลด้วย GPU

บทสรุป: บทเรียนนี้ติดตามเส้นทางสถาปัตยกรรมของหน่วยประมวลผลกราฟิก (GPU) ตั้งแต่เริ่มต้นเป็นฮาร์ดแวร์เฉพาะทางสำหรับการเรนเดอร์สามเหลี่ยม จนกลายมาเป็นโปรเซสเซอร์ขนานที่ทรงพลังและเป็นหน่วยประมวลผลทั่วไปแบบรวมศูนย์ นักเรียนจะสำรวจการเปลี่ยนผ่านจากเส้นทางกราฟิกที่ตายตัว มาเป็นชูดิโอที่เขียนโปรแกรมได้ ปรากฏการณ์ของ "GPGPU" และสถาปัตยกรรมที่ทันสมัยที่ขับเคลื่อนการจำลองทางวิทยาศาสตร์และวิศวกรรมในปัจจุบัน

ผลลัพธ์การเรียนรู้:

  • เปรียบเทียบ ความแตกต่างทางสถาปัตยกรรมระหว่างเส้นทางการทำงานแบบคงที่ (fixed-function pipelines) กับอาร์เรย์โปรเซสเซอร์ที่สามารถเขียนโปรแกรมได้ (programmable unified processor arrays)
  • อธิบาย บทบาทของ "GPGPU" เป็นขั้นตอนกลาง และข้อจำกัดของโมเดลการเขียนโปรแกรมชูดิโอ (shader programming) แบบดั้งเดิม
  • วิเคราะห์ ว่าฟีเจอร์ฮาร์ดแวร์เช่น การดำเนินการแบบอะตอม (atomic operations), การซิงโครไนซ์แบบบาร์เรียร์ (barrier synchronization), และการรองรับเลขทศนิยมสองตำแหน่ง (double-precision support) สนับสนุนการเปลี่ยนผ่านสู่การประมวลผลทั่วไปที่ขยายขนาดได้

🔹 บทเรียนที่ 3: โครงสร้างโปรแกรม CUDA และการจัดการหน่วยความจำ

บทสรุป: บทเรียนนี้ครอบคลุมสถาปัตยกรรมพื้นฐานของโปรแกรม CUDA โดยเน้นความแตกต่างระหว่างการประมวลผลบนโฮสต์ (CPU) และอุปกรณ์ (GPU) นักเรียนจะเรียนรู้การระบุความขนานข้อมูลในปฏิบัติการเมทริกซ์ การจัดการพื้นที่หน่วยความจำแยกต่างหากด้วยไลบรารี CUDA API และจัดระเบียบการประมวลผลแบบขนานผ่านโครงสร้างของกริด บล็อก และเธรด โดยใช้สไตล์ Single-Program, Multiple-Data (SPMD)

ผลลัพธ์การเรียนรู้:

  • ระบุและใช้ประโยชน์จากความขนานข้อมูลภายในอัลกอริธึมการคูณเมทริกซ์กับเมทริกซ์
  • นำเสนอบริหารหน่วยความจำบนอุปกรณ์ (device memory management) รวมถึงการจัดสรร การถ่ายโอนข้อมูลระหว่างโฮสต์กับอุปกรณ์ และการปล่อยหน่วยความจำกลับ
  • สร้างและเริ่มต้นเคอร์เนลใน CUDA โดยใช้การดัชนีเธรดและการกำหนดโครงสร้างกริด/บล็อกที่เหมาะสม

🔹 บทเรียนที่ 4: การจัดการเธรดและแผนงานขั้นสูงใน CUDA

บทสรุป: บทเรียนนี้สำรวจโครงสร้างระดับเธรดใน CUDA โดยเน้นว่าการดัชนีแบบหลายมิติจะถูกแมปไปยังข้อมูลจริงและทรัพยากรฮาร์ดแวร์อย่างไร มันอธิบายกลไกการซิงโครไนซ์แบบบาร์เรียร์และการขยายขนาดที่ไม่ต้องมองเห็น จบลงด้วยหลักการสถาปัตยกรรมของการจัดสรรเธรดและการจัดตารางแบบแบ่งเป็นเวฟ (warp-based scheduling) ที่ใช้เพื่อทนต่อความหน่วงเวลาในระบบประมวลผลประสิทธิภาพสูง

ผลลัพธ์การเรียนรู้:

  • ออกแบบ โครงสร้างระดับเธรดแบบหลายมิติ (กริดและบล็อก) เพื่อจับคู่โครงสร้างข้อมูลที่ซับซ้อนเข้ากับฮาร์ดแวร์ GPU
  • นำไปใช้ การดัชนีข้อมูลอย่างแม่นยำโดยใช้ตัวแปรในระบบ CUDA ที่มีอยู่ (blockIdx, threadIdx, blockDim)
  • ประยุกต์ใช้ การซิงโครไนซ์แบบบาร์เรียร์เพื่อให้มั่นใจในความถูกต้องของข้อมูล พร้อมคงความสามารถในการขยายขนาดที่ไม่ต้องมองเห็นในสถาปัตยกรรม GPU ต่างๆ

🔹 บทเรียนที่ 5: การปรับปรุงประสิทธิภาพหน่วยความจำและการแบ่งส่วนหน่วยความจำแบบทีลิ่ง (Tiling)

บทสรุป: บทเรียนนี้สำรวจว่าความกว้างของแบนด์วิดธ์หน่วยความจำและข้อจำกัดทรัพยากรเป็นตัวบล็อกหลักในการประมวลผลแบบขนาน มันอธิบายการใช้เทคนิค "ทีลิ่ง" เพื่อลดการไหลของข้อมูลในหน่วยความจำระดับโลก และอธิบายบทบาทสำคัญของบาร์เรียร์ซิงโครไนซ์ (__syncthreads()) และการเลือกใช้เรจิสเตอร์หรือหน่วยความจำแชร์ (shared memory) อย่างชาญฉลาดเพื่อเพิ่มประสิทธิภาพ

ผลลัพธ์การเรียนรู้:

  • วิเคราะห์ว่าข้อจำกัดของเรจิสเตอร์และหน่วยความจำแชร์กำหนดระดับของความขนาน (occupancy) ในเคอร์เนลได้อย่างไร
  • วัดปริมาณการลดการใช้แบนด์วิดธ์หน่วยความจำระดับโลกที่ได้จากการใช้เทคนิคทีลิ่ง
  • ระบุความจำเป็นในการใช้ฟังก์ชันซิงโครไนซ์เพื่อรักษาความถูกต้องของข้อมูลขณะเข้าถึงหน่วยความจำแชร์

🔹 บทเรียนที่ 6: การวิเคราะห์ประสิทธิภาพและสถาปัตยกรรมการดำเนินการแบบ SIMT

บทสรุป: บทเรียนนี้สำรวจปัจจัยทางสถาปัตยกรรมและอัลกอริธึมที่จำเป็นต่อการปรับปรุงประสิทธิภาพของเคอร์เนลใน CUDA บทเรียนนี้เปลี่ยนจากโมเดลการดำเนินการพื้นฐาน — โดยเฉพาะหน่วยแบบ Single-Instruction, Multiple-Thread (SIMT) และการแบ่งเวฟ (warp partitioning) — สู่เทคนิคการปรับประสิทธิภาพขั้นสูง เช่น การรวมข้อมูลหน่วยความจำ (memory coalescing), การคูณเมทริกซ์แบบทีลิ่ง (tiled matrix multiplication) และการแบ่งทรัพยากรใน Streaming Multiprocessor (SM) แบบไดนามิก

ผลลัพธ์การเรียนรู้:

  • วิเคราะห์ การจับคู่บล็อกเธรดหลายมิติเข้ากับลำดับการดำเนินการแบบเส้นตรงของเวฟในฮาร์ดแวร์
  • ประเมิน และลดการแตกต่างของควบคุมโฟลว์ (control flow divergence) ในอัลกอริธึมการลดขนาดแบบขนาน
  • เพิ่มประสิทธิภาพแบนด์วิดธ์หน่วยความจำระดับโลก โดยการใช้การรวมข้อมูลหน่วยความจำ (memory coalescing) และรูปแบบการเข้าถึงข้อมูลแบบทีลิ่ง

🔹 บทเรียนที่ 7: การคำนวณเลขทศนิยมและความแม่นยำทางตัวเลข

บทสรุป: บทเรียนนี้ครอบคลุมสถาปัตยกรรมพื้นฐานของจำนวนทศนิยม โดยเน้นส่วนประกอบมาตรฐาน IEEE 754 ได้แก่ สัญลักษณ์ (sign), เอ็กซ์โพเนนต์ที่เข้ารหัสแบบเกิน (excess-encoded exponent), และแมนทิสซาที่ปกติ (normalized mantissa) นักเรียนจะสำรวจว่ารูปแบบบิตเหล่านี้ถูกแมปไปยังเส้นจำนวนแบบดิสครีตอย่างไร และข้อจำกัดของรูปแบบนี้ส่งผลต่อความแม่นยำของอัลกอริธึมซับซ้อน เช่น การรวมจำนวนมาก

ผลลัพธ์การเรียนรู้:

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

🔹 บทเรียนที่ 8: กรณีศึกษา – การประมวลผลขนานในกระบวนการกู้คืนภาพ MRI

บทสรุป: บทเรียนนี้สำรวจการประมวลผลขนานในกระบวนการกู้คืนภาพการถ่ายภาพเอกซเรย์ทางความถี่ (MRI) บน GPU โดยเน้นกระบวนการกู้คืนแบบวนซ้ำสำหรับเส้นทางไม่เป็นเชิงเส้น (non-Cartesian trajectories) โดยเฉพาะการปรับปรุงเคอร์เนลที่คำนวณหนัก F^H d ผ่านการเปลี่ยนแปลงลูป การจัดการหน่วยความจำคงที่ การจัดเรียงข้อมูลใหม่ และการใช้ฟังก์ชันตรีโกณมิติที่เร่งด้วยฮาร์ดแวร์

ผลลัพธ์การเรียนรู้:

  • เข้าใจการเปลี่ยนผ่านจากวิธีกู้คืนแบบใช้ FFT แบบคาร์ทีเซียน มาเป็นอัลกอริธึมการแก้สมการเชิงเส้นแบบวนซ้ำสำหรับข้อมูลในโดเมนค่าความถี่ไม่เป็นเชิงเส้น (non-Cartesian k-space)
  • ประยุกต์ใช้การแยกลูป (loop fission) และการสลับลำดับลูป (loop interchange) เพื่อเปลี่ยนโค้ด C แบบลำดับเป็นโครงสร้างที่เหมาะกับการจัดสรรเธรดใน CUDA จำนวนมาก
  • ปรับปรุงประสิทธิภาพการไหลของหน่วยความจำโดยใช้การแบ่งหน่วยความจำคงที่ (constant memory chunking) และโครงสร้างข้อมูลแบบ Array-of-Structs (AoS)

🔹 บทเรียนที่ 9: กรณีศึกษา – การมองเห็นโมเลกุลและการทำงานแบบหลาย GPU

บทสรุป: บทเรียนนี้สำรวจการประยุกต์ใช้ GPU ในการมองเห็นโมเลกุล โดยเฉพาะการใช้วิธี Direct Coulomb Summation (DCS) เพื่อคำนวณแผนที่ศักย์ไฟฟ้าสถิต นักเรียนจะก้าวจากเคอร์เนลพื้นฐานไปสู่เวอร์ชันที่ปรับปรุงสูงสุด ซึ่งใช้การขยายคำสั่ง (instruction unrolling), การรวมข้อมูลหน่วยความจำ (memory coalescing), และการเติมข้อมูล (padding)

ผลลัพธ์การเรียนรู้:

  • สร้างเคอร์เนล Direct Coulomb Summation (DCS) โดยใช้หน่วยความจำคงที่ (CUDA constant memory) และเทคนิคการซ่อนความล่าช้าของหน่วยความจำแบบทั่วไป (global memory latency-hiding)
  • ปรับปรุงประสิทธิภาพเคอร์เนลโดยการขยายคำสั่ง (instruction unrolling) และการนำกลับมาใช้คำนวณพิกัดที่เหมือนกัน
  • ใช้กลยุทธ์การรวมข้อมูลหน่วยความจำ (memory coalescing) และการเติมข้อมูล (padding) เพื่อจัดเรียงการเข้าถึงหน่วยความจำแบบทั่วไปของ GPU ให้ได้แบนด์วิดธ์สูงสุด

🔹 บทเรียนที่ 10: การคิดเชิงคำนวณและการเลือกอัลกอริธึมแบบขนาน

บทสรุป: บทเรียนนี้สำรวจการเปลี่ยนผ่านจากความคิดแบบลำดับไปสู่การแก้ปัญหาแบบขนาน โดยเน้นเป้าหมายของการเขียนโปรแกรมแบบขนานและการเลือกอัลกอริธึมอย่างมีกลยุทธ์ นักเรียนจะเรียนรู้การแยกปัญหาออกเป็นหน่วยที่สามารถประมวลผลแบบขนานได้ ประยุกต์การคิดเชิงคำนวณเพื่อสะ bridges ช่องว่างระหว่างวิทยาศาสตร์สาขาต่าง ๆ กับสถาปัตยกรรมฮาร์ดแวร์ และประเมินประสิทธิภาพของอัลกอริธึม

ผลลัพธ์การเรียนรู้:

  • ระบุเป้าหมายหลักของการเขียนโปรแกรมแบบขนาน และคำนวณความเร็วที่เป็นไปได้ทางทฤษฎีโดยใช้กฎของ Amdahl
  • แยกแยะระหว่างการแยกตามงาน (task-level decomposition) และการแยกตามข้อมูล (data-level decomposition) และประยุกต์ใช้กลยุทธ์แบบตัวอะตอม (atom-centric, scatter) เทียบกับแบบกริด (grid-centric, gather)
  • ประเมินและเลือกอัลกอริธึมแบบขนานตามเกณฑ์ เช่น แบนด์วิดธ์หน่วยความจำ ความซับซ้อนเชิงคำนวณ และข้อจำกัดทางสถาปัตยกรรม

🔹 บทเรียนที่ 11: บทนำสู่โมเดลการเขียนโปรแกรม OpenCL

บทสรุป: บทเรียนนี้แนะนำ OpenCL เป็นเฟรมเวิร์กสำหรับการประมวลผลขนานแบบหลากหลาย โฟกัสที่โมเดลการขนานข้อมูลและความสามารถในการสร้างภาพรวมฮาร์ดแวร์แบบระดับชั้น นักเรียนจะเรียนรู้การจับคู่โครงสร้าง NDRange และหน่วยความจำของ OpenCL เข้ากับสถาปัตยกรรมเฉพาะของ CUDA และควบคุมอุปกรณ์จากฝั่งโฮสต์ผ่านโมเดลการคอมไพล์แบบไดนามิก

ผลลัพธ์การเรียนรู้:

  • จับคู่การขนานและการจัดลำดับหน่วยความจำของ OpenCL เข้ากับสถาปัตยกรรมเฉพาะของ CUDA (เช่น การจับคู่ Work-groups กับ Blocks และ Local Memory กับ Shared Memory)
  • สร้างฟังก์ชันเคอร์เนล OpenCL และจัดการสภาพแวดล้อมการประมวลผลจากฝั่งโฮสต์โดยใช้ Contexts และ Command Queues
  • ดำเนินการกระบวนการทำงานการคอมไพล์แบบไดนามิก เพื่อสร้างเคอร์เนลจากโค้ดแหล่งที่มาในช่วงเวลาทำงาน

🔹 บทเรียนที่ 12: คุณสมบัติ GPU สมัยใหม่และแนวโน้มในอนาคต

บทสรุป: บทเรียนนี้สำรวจการเปลี่ยนแปลงทางสถาปัตยกรรมและฟังก์ชันของ GPU โดยเน้นการเปลี่ยนผ่านสู่การจัดการหน่วยความจำที่ซับซ้อนมากขึ้น ความสามารถในการประมวลผลเคอร์เนลที่ดีขึ้น และประสิทธิภาพของคอร์ที่เพิ่มขึ้น นักเรียนจะพิจารณาฟีเจอร์ต่างๆ เช่น Unified Device Memory Space และการเรียกฟังก์ชันระดับเคอร์เนล ที่ทำให้ GPU กลายเป็นโปรเซสเซอร์ทั่วไป

ผลลัพธ์การเรียนรู้:

  • อธิบายความสำคัญของการพัฒนาสถาปัตยกรรมหน่วยความจำ และการเปลี่ยนผ่านสู่ Unified Device Memory Space แบบ 64-bit
  • วิเคราะห์ว่าการเสริมฟังก์ชันอะตอม (Enhanced Atomic Operations) และการเรียกฟังก์ชันระดับเคอร์เนล (kernel-level Function Calls) ช่วยให้สามารถใช้งานโครงสร้างข้อมูลและอัลกอริธึมที่ซับซ้อนได้อย่างไร
  • ประเมินผลกระทบต่อประสิทธิภาพจากการทำงานเคอร์เนลพร้อมกัน (Simultaneous Kernel Execution), การปรับปรุงความเร็วของเลขทศนิยมสองตำแหน่ง (Double-Precision Speed), และประสิทธิภาพการควบคุมโฟลว์ (Control Flow Efficiency) ในสภาพแวดล้อม GPU สมัยใหม่