Parallel Systems · จาก Parallel Algorithms ไปสู่ระบบขนานสมัยใหม่
Parallel Systems
Warin Wattanapornprom, PhD.
วิชานี้เริ่มจากคำถามที่ดูเหมือนง่ายว่า “ถ้าเครื่องเดียวทำงานไม่ทัน เราแบ่งงานให้หลายหน่วยประมวลผลช่วยกันได้หรือไม่” แต่คำถามจริงที่ซ่อนอยู่ยากกว่านั้นมาก: แบ่งงานตรงไหน ส่งข้อมูลอย่างไร รักษาลำดับอะไร และทำอย่างไรให้เวลาที่ประหยัดได้มากกว่าต้นทุนของการทำงานร่วมกัน
9 บท จากซีพียูสู่ระบบขนาดใหญ่
4 หมวด สถาปัตยกรรม โปรแกรม การวัด และระบบ
2002 → 2026 บทเรียนที่เดินทางมากว่าสองทศวรรษ
8 CPU จาก 7.5 วัน เหลือ 8 ชั่วโมง
ความตั้งใจ
เรื่องเล่าปี 2002
Superlinear Speedup
เส้นทางการเรียน
พื้นฐานที่ควรมี
การปรับเนื้อหา
คำขอบคุณ
คำนำและความตั้งใจของผู้สอน
Parallel Computing ไม่ได้เริ่มจากการมีเครื่องหลายตัว แต่เริ่มจากการมองเห็นว่างานแบ่งตรงไหนได้
หลายคนพบ Parallel Computing ครั้งแรกในรูปของคำสั่งสร้าง thread, การเรียก MPI หรือการส่งงานขึ้น GPU จึงเผลอเข้าใจว่าวิชานี้เป็นวิชาว่าด้วยเครื่องมือ แต่เครื่องมือเป็นเพียงปลายทางของการตัดสินใจ สิ่งที่ยากกว่าคือมองโจทย์หนึ่งแล้วแยกให้ออกว่าอะไรทำพร้อมกันได้ อะไรต้องรอ และข้อมูลชิ้นใดควรอยู่ใกล้หน่วยประมวลผลใด
ถ้าแบ่งงานผิด ต่อให้มี CPU หนึ่งพันตัวก็อาจรอคิวเดียวกัน ถ้าส่งข้อมูลมากเกินไป เวลาที่ได้จากการคำนวณพร้อมกันจะถูกใช้ไปกับการเคลื่อนย้ายข้อมูล และถ้า workload เล็กเกินไป การตั้งทีมอาจใช้เวลามากกว่าการทำงานเสียเอง
ภาพเปรียบเทียบ: ครัวที่มีพ่อครัวแปดคน การเพิ่มพ่อครัวจากหนึ่งคนเป็นแปดคนไม่ได้ทำให้อาหารเสร็จเร็วขึ้นแปดเท่าโดยอัตโนมัติ ถ้าทุกคนต้องใช้มีดเล่มเดียว เตาเดียว หรือรอหัวหน้าครัวชิมทุกจาน ปัญหาของ Parallel Systems จึงไม่ใช่การหาคนเพิ่ม แต่เป็นการออกแบบครัวใหม่ให้งาน วัตถุดิบ และอุปกรณ์ไม่ขวางกันเอง
เอกสารชุดนี้จึงไม่ได้เรียงตามชื่อเทคโนโลยี แต่พาผู้อ่านเดินจากเหตุผลที่ต้องทำงานแบบขนาน เข้าไปดู parallelism ที่ซ่อนอยู่ภายใน CPU แยกประเภทของงานขนาน ทำความเข้าใจสถาปัตยกรรม จากนั้นจึงเขียนโปรแกรม วัดผล และขยายมุมมองออกไปสู่ cloud กับ data services
เป้าหมายไม่ใช่ให้ใช้เครื่องได้หลายตัว แต่ให้คิดเป็นว่าเมื่อใดหลายตัวจึงคุ้มกว่าตัวเดียว
เรื่องเล่าจากปี 2002
งานที่ใช้เวลา 7.5 วัน และคอมพิวเตอร์แปดตัวที่ไม่ได้ให้เพียงความเร็วแปดเท่า
เมื่อปี 2002 ผมใช้ Parallel Algorithms แก้ปัญหา Bioinformatics ที่อาศัย Dynamic Programming ปัญหาลักษณะนี้สร้างตารางขนาดใหญ่ แต่ละช่องขึ้นอยู่กับผลลัพธ์บางช่องที่คำนวณมาก่อน จึงไม่สามารถโยนทุกช่องให้ CPU คนละตัวแล้วเริ่มพร้อมกันได้ทั้งหมด
โจทย์จริงคือหาแนวรบของการคำนวณ หรือ wavefront ซึ่งชุดของเซลล์บนแนวเดียวกันคำนวณพร้อมกันได้หลังข้อมูลที่จำเป็นจากแนวก่อนหน้าพร้อมแล้ว จากนั้นจึงแบ่งพื้นที่ ส่งค่าขอบเขตระหว่างหน่วยประมวลผล และพยายามให้แต่ละตัวมีงานใกล้เคียงกัน
จุดเริ่มต้น — 7.5 วัน การประมวลผลแบบเดิมต้องใช้เวลาประมาณเจ็ดวันครึ่ง งานหนึ่งรอบยาวจนการทดลองและปรับสมมติฐานทำได้ช้ามาก
ออกแบบ Parallel Algorithm ไม่ได้เพียงนำโปรแกรมเดิมไปเปิดแปดสำเนา แต่ต้องจัด dependency, decomposition, communication และตำแหน่งข้อมูลใหม่
ผลลัพธ์ — 8 ชั่วโมง บน CPU 8 ตัว เวลาลดลงจากประมาณ 180 ชั่วโมงเหลือ 8 ชั่วโมง คิดเป็น speedup ราว 22.5 เท่า ทั้งที่ใช้ CPU เพียงแปดตัว
สิ่งที่พบ — Superlinear Speedup ความเร็วที่เพิ่มขึ้นมากกว่าจำนวน CPU ไม่ได้มาจากการละเมิดคณิตศาสตร์ แต่มาจากการที่ข้อมูลย่อยของแต่ละหน่วยประมวลผลเข้ากับ cache ได้ดีขึ้น ลด cache miss และการรอหน่วยความจำอย่างมาก
180 ชั่วโมง เวลาประมาณการแบบเดิม
8 ชั่วโมง เวลาหลังทำงานแบบขนาน
≈22.5× Speedup ที่สังเกตได้
8 CPU จำนวนหน่วยประมวลผล
Speedup S(p) = T(1) / T(p) ≈ 180 / 8 = 22.5Efficiency E(p) = S(p) / p ≈ 22.5 / 8 = 2.8125
หากดูตัวเลขอย่างผิวเผิน Efficiency มากกว่า 1 ดูเหมือนเป็นไปไม่ได้ เพราะ CPU แปดตัวไม่น่าทำงานแทนยี่สิบสองตัวได้ แต่จุดอ้างอิงของการเปรียบเทียบไม่ได้มีต้นทุนทางหน่วยความจำเหมือนกัน โปรแกรมแบบขนานเปลี่ยน working set ต่อ CPU และเปลี่ยนพฤติกรรมของ cache ดังนั้นสิ่งที่ลดลงไม่ได้มีเพียงจำนวน operation ต่อหน่วยประมวลผล แต่รวมถึง overhead ที่เคยซ่อนอยู่ใน memory hierarchy
ทำความเข้าใจ Superlinear Speedup ให้ถูกต้อง
เร็วเกินจำนวน CPU ไม่ใช่เวทมนตร์ และไม่ควรรีบเรียกว่า algorithm ใหม่
โดยทั่วไป ถ้าเพิ่มหน่วยประมวลผลเป็น p ตัว เราคาดหวัง speedup ไม่เกิน p เพราะงานทั้งหมดไม่ได้หายไป เพียงถูกแบ่งกันทำ แต่การวัดเวลาบนเครื่องจริงยังรวม cache miss, memory paging, search pruning, I/O และ behavior ของ runtime ถ้าการแบ่งงานช่วยกำจัดต้นทุนบางส่วนที่การทำงานแบบลำดับต้องจ่าย ผลลัพธ์อาจดูเร็วกว่า p เท่าได้
สาเหตุที่เป็นไปได้ เกิดอะไรขึ้น สิ่งที่ควรตรวจสอบ
Cache locality ดีขึ้น Working set ต่อ CPU เล็กลงและพอดีกับ cache มากกว่าเดิม Cache miss, memory bandwidth และขนาดข้อมูลต่อ worker
Paging ลดลง การแบ่งข้อมูลช่วยให้แต่ละ process ไม่ต้องสลับหน้าหน่วยความจำบ่อย Page fault และ resident set size
ค้นหาเจอคำตอบเร็วขึ้น การค้นหาหลายเส้นทางพร้อมกันอาจพบคำตอบดีเร็วจนตัดกิ่งอื่นได้มากขึ้น จำนวน state ที่สำรวจจริง ไม่ใช่ดูเวลาอย่างเดียว
Baseline ไม่เท่ากัน โค้ดแบบลำดับอาจไม่ได้ optimize เท่ากับโค้ดแบบขนาน Compiler flags, algorithm, data type และ preprocessing ต้องเทียบอย่างเป็นธรรม
ระบบวัดคลาดเคลื่อน รวม I/O หรือ setup คนละขอบเขต ใช้ข้อมูลคนละชุด หรือมีงานอื่นรบกวน นิยาม T(1), warm-up, repetitions และ confidence interval
ข้อควรระวัง Superlinear Speedup เป็นผลลัพธ์ที่น่าสนใจ แต่ยิ่งตัวเลขสวยยิ่งต้องตรวจให้ละเอียด การอธิบายว่า “เพราะ cache” ควรมีหลักฐานจาก hardware counter หรือการทดลองเปลี่ยน working-set size ไม่เช่นนั้นเรากำลังตั้งชื่อให้ปรากฏการณ์ มากกว่ากำลังอธิบายมัน
บทเรียนสำคัญจากปี 2002 จึงไม่ใช่เพียงว่าใช้ CPU แปดตัวแล้วเร็วขึ้น แต่คือ performance เกิดจากความสัมพันธ์ระหว่าง algorithm, decomposition และ architecture โปรแกรมเดียวกันอาจเร็วหรือช้าอย่างมากเพียงเพราะข้อมูลวางอยู่คนละระดับของ memory hierarchy
เมื่อความรู้เดินทางผ่านเวลา
จาก Parallel Algorithms บน CPU แปดตัว ไปสู่ Dynamic Programming บน Apache Spark
เวลาผ่านไปกว่ายี่สิบปี เครื่องมือเปลี่ยนจากการจัดการ CPU โดยตรงไปเป็น cluster framework อย่าง Apache Spark เครื่องใหญ่ขึ้น ข้อมูลใหญ่ขึ้น และระบบจัดการงานให้หลายอย่าง แต่ dependency ของ Dynamic Programming, ต้นทุน communication, data locality และ cache behavior ไม่ได้หายไป
ปีที่แล้ว ผมนำแนวคิดชุดเดียวกันไปสอนในวิชา Big Data Analytics ให้กับนักศึกษาสาขาสถิติ มีนักศึกษาคนหนึ่งตั้งใจเรียนมากและได้เกรด A ต่อมาเขาส่งข่าวกลับมาว่าได้นำหลักการนี้ไปแก้ปัญหา Dynamic Programming ที่มีขนาดใหญ่กว่าเดิมมากบน Apache Spark
ผลลัพธ์ที่ส่งกลับมา งานซึ่งหากประมวลผลตามเดิมต้องใช้เวลากว่าหนึ่งปี ลดลงเหลือเพียงประมาณ 13 ชั่วโมง และพบ Superlinear Speedup ในลักษณะที่เชื่อมโยงกับการจัดข้อมูลและลด overhead เช่นเดียวกับงานเมื่อปี 2002
อ่านแล้วผมนั่งยิ้มอยู่พักใหญ่ ตลอดชีวิตการสอน มีลูกศิษย์หลายคนสานต่อความรู้ในสาย AI, Machine Learning และ Algorithms แต่ครั้งนี้เป็นครั้งแรกที่รู้สึกชัดว่า มีคนสืบทอดวิชาสาย Parallel Computing แล้ว
ที่สำคัญ เขาไม่ได้เพียงรู้วิธีส่งงานขึ้น Spark หรือเพิ่มจำนวน executor แต่เข้าใจหลักการลึกพอที่จะมองเห็นว่าเวลาหายไปตรงไหน และจัดโครงสร้างการคำนวณจนเกิด Superlinear Speedup ในโจทย์อีกยุคหนึ่ง เครื่องมือเปลี่ยน แต่ pattern เดิมเดินทางข้ามเวลามาถึงคนรุ่นใหม่
สำหรับอาจารย์ งานวิจัยอาจเป็นหลักฐานว่าเราเคยค้นพบอะไรบางอย่าง แต่ลูกศิษย์คือหลักฐานว่าความรู้นั้นยังเดินทางต่อได้
ความสุขจึงไม่ได้อยู่ที่ผลงานของตัวเองเพียงอย่างเดียว แต่อยู่ที่วันที่เห็นความรู้ที่เคยสอนถูกนำไปใช้ เติบโต และไปไกลกว่าที่ผู้สอนเคยทำ ขอบคุณที่ตั้งใจเรียน และทำให้วิชาที่ผมรักมีคนรุ่นต่อไปช่วยสานต่อครับ
วิชานี้อยู่ตรงไหนในภาพรวม
Parallel, Distributed และ Scalable Systems เป็นญาติกัน แต่ถามคนละคำถาม
ทั้งสามวิชาพูดถึงการมีองค์ประกอบหลายส่วนทำงานร่วมกัน จึงมีเนื้อหาทับซ้อนกัน แต่จุดเริ่มต้นต่างกัน Parallel Systems เริ่มจากการลดเวลาประมวลผล Distributed Systems เริ่มจากความถูกต้องเมื่อเครื่องและเครือข่ายล้มเหลวบางส่วน ส่วน Scalable Computing พยายามรวมทั้งสองมุม แล้วถามว่าระบบจะเติบโตโดยยังคุ้มค่าและรักษาสัญญาได้อย่างไร
มุมมอง คำถามตั้งต้น สิ่งที่มักวัด ความล้มเหลวที่กลัว
Parallel Systems ทำอย่างไรให้งานหนึ่งเสร็จเร็วขึ้น Runtime, speedup, efficiency, scalability Dependency, imbalance, communication และ contention
Distributed Systems หลายเครื่องจะรักษาความหมายร่วมกันได้อย่างไร Correctness, availability, consistency, recovery Partial failure, message delay, partition และ replica disagreement
Scalable Computing เมื่อขยาย workload และทรัพยากร ระบบยังคุ้มค่าเพียงใด Throughput, tail latency, cost, energy และ scalability envelope คอขวดที่ย้ายตำแหน่ง, overhead และต้นทุนโตเร็วกว่าประโยชน์
ในโลกจริงขอบเขตไม่เรียบร้อยแบบรายวิชา GPU cluster เป็นทั้ง parallel และ distributed ระบบ Spark ต้องคิดทั้ง dependency graph, partitioning, locality, straggler และ failure recovery ส่วนบริการขนาดใหญ่ต้องใช้ parallelism ภายในเครื่องและ distribution ระหว่างเครื่องพร้อมกัน
หลักคิดที่อยากให้ติดตัว อย่าเริ่มด้วยคำถามว่า “ควรใช้ MPI, CUDA หรือ Spark” ให้เริ่มด้วยคำถามว่า work อยู่ตรงไหน dependency เป็นอย่างไร ข้อมูลอยู่ที่ใด ต้องสื่อสารมากแค่ไหน และสัญญาใดห้ามเสีย จากนั้นเครื่องมือที่เหมาะสมจะค่อย ๆ แคบลงเอง
เส้นทางการเรียนรู้
จากงานหนึ่งชิ้น ไปสู่หลายคำสั่ง หลายแกน หลายเครื่อง และหลายศูนย์ข้อมูล
โครงสร้าง 9 บทถูกจัดใหม่ให้เดินจากภายในออกสู่ภายนอก เราเริ่มที่เหตุผลว่าทำไมต้องขนาน มอง parallelism ที่ CPU ทำให้เราโดยไม่รู้ตัว จากนั้นเรียนรู้วิธีแบ่งงาน สถาปัตยกรรม การเขียนโปรแกรม และการวัดผล ก่อนขยายไปสู่ระบบขนาดใหญ่
1 · ทำไมต้องขนาน
เริ่มจากข้อจำกัดของเครื่องเดี่ยวและโจทย์ที่ใหญ่เกินกว่าจะรอให้ clock เร็วขึ้น
2 · ขนานภายในเครื่องเดียว
ก่อนขยายไปหลายเครื่อง ต้องเห็นก่อนว่าซีพียูและหน่วยความจำสร้างหรือจำกัด parallelism อย่างไร
บทที่ 2
Parallelism Inside a CPU Pipeline, hazards, superscalar, out-of-order execution และข้อจำกัดของ Instruction-Level Parallelism
บทที่ 3
Types of Parallelism Data, functional และ pipeline parallelism พร้อม Data Dependence Graph และ granularity
บทที่ 4
Parallel Architecture Flynn's Taxonomy, SMP, PVP, MPP, DSM, cluster, NUMA และสิ่งที่แนวคิดเหล่านี้กลายเป็นในปัจจุบัน
3 · เขียนโปรแกรมและวัดผล
เปลี่ยนแบบจำลองให้เป็นโปรแกรม และแยกให้ออกว่าเร็วขึ้นเพราะ parallelism จริงหรือเพราะวัดคนละเงื่อนไข
4 · จากงานขนานไปสู่ระบบขนาดใหญ่
เมื่อหน่วยประมวลผลไม่ได้อยู่ในเครื่องเดียว ปัญหา performance เริ่มพบกับเครือข่าย virtualization, storage และ distributed data services
พื้นฐานที่ควรมี
ไม่จำเป็นต้องรู้ทุก framework แต่ต้องอ่าน dependency และต้นทุนให้ออก
วิชานี้อ่านได้ตั้งแต่ระดับปริญญาตรีช่วงปลายเป็นต้นไป หากมีพื้นฐานต่อไปนี้จะช่วยให้เห็นเหตุผลเบื้องหลังได้มากกว่าการจำคำศัพท์
Data Structures & Algorithms เข้าใจ complexity, graph, recursion, Dynamic Programming และการแยก correctness ออกจาก performance
Computer Architecture รู้จัก CPU, cache, memory hierarchy, pipeline และเหตุผลที่ memory access ไม่ได้มีราคาเท่ากันทั้งหมด
Operating Systems เข้าใจ process, thread, synchronization, virtual memory และต้นทุนของ context switch กับ I/O
Computer Networks เข้าใจ latency, bandwidth, packet loss และความต่างระหว่างการเข้าหน่วยความจำกับการส่งข้อมูลข้ามเครื่อง
Programming เขียนโปรแกรมด้วยภาษาใดภาษาหนึ่งได้คล่องพอจะแยกปัญหาของ algorithm ออกจาก syntax
การทดลองและสถิติ วัดซ้ำ อ่านค่าเฉลี่ยกับ percentile และระวัง benchmark ที่สวยเพราะเลือกเงื่อนไขเข้าข้างตนเอง
ถ้าพื้นฐานบางส่วนยังไม่แน่น ไม่ได้แปลว่าเรียนต่อไม่ได้ แต่ควรย้อนอ่านเมื่อติดขัด โดยเฉพาะเรื่อง cache และ dependency เพราะสองเรื่องนี้อธิบายทั้งความเร็วที่ได้และเพดานที่ไปต่อไม่ได้ในหลายบท
วิธีอ่านเนื้อหาชุดนี้
อ่านทุกบทด้วยคำถามห้าข้อ
Work: งานทั้งหมดมีเท่าใด และงานส่วนใดทำพร้อมกันได้
Dependency: งานใดต้องรอผลจากงานใด มี critical path ยาวเท่าใด
Placement: Code และข้อมูลอยู่ที่ไหน ใกล้หน่วยประมวลผลพอหรือไม่
Communication: ต้องแลกข้อมูลกี่ครั้ง ปริมาณเท่าใด และรอพร้อมกันตรงไหน
Measurement: เร็วขึ้นเมื่อเทียบกับอะไร รวม setup, I/O และ recovery ไว้หรือยัง
คำถามเหล่านี้ใช้ได้ตั้งแต่ pipeline ใน CPU, loop บน GPU, MPI cluster ไปจนถึง Spark job เมื่อเทคโนโลยีเปลี่ยน เราอาจต้องเรียน API ใหม่ แต่โครงคำถามยังคงเดิม นั่นคือเหตุผลที่วิชาซึ่งมีรากจากเอกสารเก่ากว่าสิบปีสามารถนำกลับมาสอนได้โดยไม่กลายเป็นพิพิธภัณฑ์คอมพิวเตอร์
อะไรคงเดิม และอะไรได้รับการปรับให้เป็นปัจจุบัน
รักษาหลักการ เปลี่ยนตัวอย่าง และเพิ่มสิ่งที่อดีตยังมองไม่เห็น
เอกสารต้นฉบับมาจากเนื้อหา Parallel Computing และ Large Scale Computing Systems ในช่วงก่อนปี 2018 หลายแนวคิดยังเป็นรากฐานที่จำเป็น แต่ชื่อผลิตภัณฑ์ สถาปัตยกรรม และขนาดของระบบเปลี่ยนไปมาก การปรับปรุงจึงไม่ใช่การลบของเก่าทั้งหมด และไม่ใช่การเติมชื่อเทคโนโลยีใหม่ลงไปท้ายบทเท่านั้น
แกนความรู้ที่ยังจำเป็น ตัวอย่างดั้งเดิม สิ่งที่เชื่อมเพิ่มในฉบับนี้
Instruction-level parallelism Pipeline และ superscalar Out-of-order limits, speculative execution และผลข้างเคียงด้านความปลอดภัย
ประเภทของ parallelism Data, functional, pipeline SIMD/SIMT, task graph, tensor/data/model/pipeline parallelism
สถาปัตยกรรมขนาน SMP, MPP, DSM, cluster NUMA, multicore, GPU, accelerator และ cloud instance
Programming model MPI และ CUDA Collective communication, topology awareness และ heterogeneous computing
Performance model Amdahl และ Gustafson Work/span, roofline, memory wall, tail และ cost/energy
ระบบขนาดใหญ่ Multi-tier, cache, load balancer Container, Kubernetes, autoscaling และ service decomposition
บริการข้อมูล NDB, GlusterFS, Memcached NewSQL, object storage, distributed cache และ stream processing
เหมือนการเรียนแผนที่ ถนนบางสายเปลี่ยนชื่อ อาคารบางแห่งถูกรื้อ แต่ภูเขา แม่น้ำ และเหตุผลที่เมืองเติบโตตรงนั้นยังอยู่ การสอนที่ดีต้องบอกทั้งภูมิประเทศเดิมและถนนปัจจุบัน ไม่ใช่ยื่นแผนที่ปีเก่าให้ผู้เรียน หรือวาดเฉพาะร้านเปิดใหม่โดยไม่มีทิศเหนือ
ปรัชญาการสอนของเนื้อหาชุดนี้
วัดผลให้เป็น ก่อนดีใจกับตัวเลขที่เร็วขึ้น
Parallel Computing มีเสน่ห์ตรงตัวเลข ผลลัพธ์ 8×, 20× หรือ 100× ทำให้รู้สึกทันทีว่างานสำเร็จ แต่ตัวเลขเดียวกันอาจมาจากการแบ่งงานที่ดี cache ที่ดีขึ้น baseline ที่ไม่เป็นธรรม หรือการลืมนับเวลาโอนข้อมูล
ในเอกสารชุดนี้จึงพยายามแยกสามระดับออกจากกัน
Algorithmic parallelism — โจทย์เปิดโอกาสให้ทำพร้อมกันได้มากเพียงใด และ critical path อยู่ตรงไหน
Architectural realization — ฮาร์ดแวร์ หน่วยความจำ และเครือข่ายทำให้ parallelism นั้นเกิดขึ้นจริงได้แค่ไหน
Experimental evidence — การวัดพิสูจน์หรือหักล้างคำอธิบายของเราอย่างไร
ถ้ารู้เพียง API เราอาจเขียนโปรแกรมที่รันหลายตัวได้ ถ้ารู้ algorithm เราอาจวาง decomposition ได้ดี แต่ถ้าไม่เข้าใจ architecture และไม่วัดอย่างเป็นธรรม เราจะยังไม่รู้ว่าเหตุใดมันจึงเร็ว หรือเหตุใดพอขยายต่อแล้วหยุดเร็วขึ้น
โจทย์ที่อยากให้ผู้เรียนถามทุกครั้ง ถ้าเพิ่มทรัพยากรอีกเท่าตัว คอขวดจะหายไปหรือเพียงย้ายตำแหน่ง และมีหลักฐานอะไรที่ทำให้เราเชื่อคำตอบนั้น
คำขอบคุณถึงอาจารย์ผู้วางรากฐาน
ความรู้ชุดนี้ไม่ได้เกิดจากการอ่านตำราเพียงลำพัง
พื้นฐานด้าน Parallel และ Distributed Systems ของผมได้รับการประสิทธิ์ประสาทจากคณาจารย์ภาควิชาวิศวกรรมคอมพิวเตอร์ คณะวิศวกรรมศาสตร์ จุฬาลงกรณ์มหาวิทยาลัย ได้แก่ ผศ.ดร.ณัฐวุฒิ หนูไพโรจน์ , ผศ.ดร.วีระ เหมืองสิน, อ.ดร.ยรรยง เต็งอำนวย และ รศ.ดร.ทวิตีย์ เสนีวงศ์ ณ อยุธยา
อาจารย์แต่ละท่านทำให้ผมเห็นระบบจากคนละมุม ทั้ง Parallel Algorithms, Parallel Architecture, Computer Networks, Distributed Systems, system software และ large-scale services สิ่งที่ได้รับจึงไม่ใช่เพียงชื่อ algorithm หรือสูตร speedup แต่เป็นวิธีแยกโจทย์ ดูข้อสมมติ วัดต้นทุน และไม่เชื่อตัวเลขก่อนจะรู้ว่าตัวเลขนั้นเกิดขึ้นอย่างไร
เรื่องราวปี 2002 งาน Bioinformatics บน CPU แปดตัว ตลอดจนการนำหลักการเดียวกันกลับมาสอนจนมีนักศึกษานำไปใช้บน Apache Spark ในอีกยี่สิบกว่าปีต่อมา ล้วนเติบโตจากรากฐานทางความคิดที่ได้รับจากอาจารย์ทั้งสี่ท่าน
เอกสารชุดนี้เป็นการนำความรู้เหล่านั้นมาจัดระเบียบใหม่ตามประสบการณ์ทำงาน วิจัย และสอนของผม พร้อมเชื่อมเข้ากับเทคโนโลยีปัจจุบัน หากมีส่วนใดช่วยให้ผู้เรียนมองระบบได้ชัดขึ้น เครดิตสำคัญย่อมย้อนกลับไปถึงครูผู้วางรากฐาน ส่วนข้อผิดพลาดหรือการตีความที่คลาดเคลื่อนเป็นความรับผิดชอบของผู้เรียบเรียงเองครับ
เกี่ยวกับเนื้อหาชุดนี้
จากเอกสารสองวิชา สู่เส้นเรื่องเดียว
เนื้อหาทั้ง 9 บทสังเคราะห์จากเอกสารประกอบวิชา 2110732 Parallel Computing และ 2110414 Large Scale Computing Systems ซึ่งเดิมมองระบบจากระดับต่างกัน ชุดแรกเริ่มจาก algorithm กับ architecture ส่วนชุดหลังขยายไปสู่บริการขนาดใหญ่
ผมนำทั้งสองส่วนมาเรียงใหม่เป็นเส้นทางเดียว: เริ่มจากงานที่ต้องการความเร็ว เข้าไปดู parallelism ใน CPU แยกประเภทและสถาปัตยกรรม ลงมือเขียนโปรแกรม วัดว่าเร็วจริงหรือไม่ แล้วจึงขยายออกไปสู่ cloud และ data services โครงสร้างนี้ตั้งใจให้ผู้อ่านเห็นว่าระบบขนาดใหญ่ไม่ได้เกิดขึ้นคนละโลกกับ Parallel Algorithms แต่เป็นการนำหลัก decomposition, placement, communication และ measurement ไปใช้ในสเกลที่ใหญ่ขึ้น
บางบทจึงมีพื้นที่ทับซ้อนกับ Distributed Systems และ Network Computing โดยตั้งใจ เมื่อข้ามเครื่อง เราไม่สามารถคิดเฉพาะความเร็วและละเลย failure ได้ และเมื่อข้อมูลเดินทางผ่านเครือข่าย ต้นทุน communication ไม่ใช่รายละเอียดประกอบ แต่เป็นส่วนหนึ่งของ algorithm
สรุปและขั้นตอนถัดไป
เริ่มจากบทที่ 1 แล้วกลับมาอ่านเรื่องปี 2002 ใหม่อีกครั้ง
สำหรับการเรียนรอบแรก แนะนำให้เดินตามบทที่ 1–4 เพื่อสร้างภาพว่าความขนานเกิดได้หลายระดับ จากนั้นบทที่ 5 ทำให้แบบจำลองกลายเป็นโปรแกรม และบทที่ 6 สอนให้ระวังว่าตัวเลขที่เร็วขึ้นกำลังบอกอะไรจริง ๆ ส่วนบทที่ 7–9 ขยายคำถามไปสู่ระบบขนาดใหญ่ ซึ่ง performance, network และ distributed failure เริ่มแยกออกจากกันไม่ได้
เมื่ออ่านถึงการวัด performance แล้ว ลองย้อนกลับมาวิเคราะห์เรื่องปี 2002: งานส่วนใดทำพร้อมกันได้ dependency วางรูปแบบใด working set ลดลงเท่าใด cache miss เปลี่ยนอย่างไร และต้องออกแบบการทดลองแบบไหนจึงยืนยันได้ว่า Superlinear Speedup มาจาก cache locality จริง
จากนั้นลองถามคำถามเดียวกันกับ Spark: partition ใดถือข้อมูลอะไร shuffle เกิดตรงไหน task ใดเป็น straggler และการเพิ่ม executor ทำให้ communication โตเร็วกว่า computation เมื่อใด หากตอบคำถามสองยุคด้วยกรอบเดียวกันได้ แปลว่าเราไม่ได้เพียงจำเทคโนโลยี แต่เริ่มมองเห็นโครงสร้างของ Parallel Systems แล้ว
ขั้นตอนถัดไปที่แนะนำ ก่อนเปิดบทที่ 1 ให้เลือกงานหนึ่งอย่างที่ใช้เวลานาน แล้วเขียนไว้สั้น ๆ ว่า “ถ้ามี CPU เพิ่มขึ้นสิบเท่า งานนี้จะเร็วขึ้นสิบเท่าหรือไม่ เพราะอะไร” เก็บคำตอบไว้ และกลับมาเขียนใหม่หลังเรียน dependency, architecture และ Amdahl's Law ความต่างระหว่างคำตอบสองรอบจะบอกได้ดีว่ากรอบคิดเปลี่ยนไปเพียงใด
เป้าหมายปลายทางของวิชานี้ไม่ใช่การทำให้ทุกอย่าง parallel แต่คือการรู้ว่าอะไรควรขนาน ขนานตรงไหน ใช้ทรัพยากรเท่าใด และหยุดเพิ่มเมื่อใด เพราะระบบที่ดีไม่ได้ใช้เครื่องมากที่สุด แต่ใช้โครงสร้างของปัญหาได้คุ้มที่สุดครับ
เริ่มอ่านบทที่ 1: Why Parallel Systems? →
Warin Wattanapornprom, PhD.
Parallel Systems · Warin Wattanapornprom, PhD. · เรียบเรียงและปรับปรุงสำหรับการเรียนรู้ในปี 2026