ประยุกต์ Multiphase Parallel Algorithm ด้วย Barrier Class ใน .NET 4… Actions!

เกริ่นนำ

บทความนี้ผมจะมาแสดงวิธีใช้ Barrier Class ของ .NET 4 ซึ่งมันสามารถจัดการเรื่องการทำงานร่วมกันแบบ multiphase เพื่อใช้ implement งานที่มี algorithm แบบ parallel ได้โดยมันสามารถแทรกเข้าไปในงานเพื่อเป็นอุปสรรค(barrier) เพื่อให้รอการทำงานร่วมกันของผู้ร่วมงานหลายๆคนในระหว่าง phase ได้

ใช้งาน Barrier Class ตอนไหน

กรณีการใช้ Barrier Class คือเมื่อเรามีงาน(task) ที่ต้องร่วมมือกันทำงาน(cooperate) โดยมีการทำงานเป็นขั้นตอน(phase)จนเสร็จงานนี้ ซึ่งในแต่ละ phase งานจะส่งสัญญาณ(signal) ว่าทำเสร็จแล้วและต้องรอการคนอื่น(wait)ทำงานเสร็จก่อนทุกคนเพื่อทำงานใน phase ต่อไปได้ และเราต้องการใส่ barrier ที่จะเข้ามาขัดจังหวะงานในแต่ละ phase เพื่อให้แน่ใจว่าทุกคนทำงานตาม phase นี้ได้อย่างถูกต้อง ครบถ้วนสมบูรณ์แล้ว(concurrency)

มา implement Barrier Class ง่ายๆกันดีกว่า… Actions!

เริ่มจากผมมีงานที่ต้องการทำ ผมจะสมมติงานง่ายๆให้ 1 งานของผมแบ่งออกเป็น 3 phase ในแต่ละ phase ก็ให้ทำงานบวกผลผลิตไปทีละ 100 หลังจากทุกคนทำงานเสร็จในแต่ละ phase แล้วให้ barrier  report ผลรวมออกมาด้วย เอาแค่นี้พอครับ

ลำดับต่อมาผมต้องจัดคนเข้าไปทำงาน โดยผมจะเอาจำนวณ Core ของ CPU แทนจำนวนคนงานที่ผมจะมอบหมายงานให้เขาทำได้ เช่นตอนนี้เครื่องผมใช้ CPU duo core นั่นหมายความว่าผมสามารถ run งานพร้อมๆกัน(parallel) ได้ 2 งานเท่านั้น สรุปว่าผมเขียน code ได้ดังนี้

using System.Threading;
using System.Threading.Tasks;

[TestMethod]
public void TestBarrierImplementMultiphaseParallelAlgorithm()
{

    int participantCount = Environment.ProcessorCount;//ให้ผู้ร่วมทำงานครั้งละ 2 คน
    int totalProduct = 0;//กำหนด

    //กำหนด Action ให้ทำ report ผลงานออกมาทุกๆ phase
    Action<Barrier> doReport = (myBarrier) =>
    {
        Console.WriteLine(“คนงานทั้ง {0} คน ดำเนินการ phase ที่: {1} เสร็จสมบูรณ์, สรุป TotalProduct {2}”
            , participantCount, myBarrier.CurrentPhaseNumber, totalProduct);//
    };

    using (Barrier barrier = new Barrier(participantCount, doReport))
    {
        //กำหนด Action ให้ทำการผลิต ทุก phase คนงานจะเพิ่ม totalProduct ไปทีละ 100
        Action doProduce = () =>
        {
            Console.WriteLine(“คนงานที่ {0} เริ่มทำเนินการ phase ที่ {1}”, Task.CurrentId, barrier.CurrentPhaseNumber);
            //เริ่มกระบวนการผลิต phase ที่ 0
            Interlocked.Add(ref totalProduct, 100);
            barrier.SignalAndWait();//รอคนงานคนอื่นๆ produce phase ที่ 0 เสร็จก่อน

            Console.WriteLine(“คนงานที่ {0}, เริ่มทำเนินการ phase ที่ {1}”, Task.CurrentId, barrier.CurrentPhaseNumber);
            //เริ่มกระบวนการผลิต phase ที่ 1
            Interlocked.Add(ref totalProduct, 100);
            barrier.SignalAndWait();//รอคนงานคนอื่นๆ produce phase ที่ 1 เสร็จก่อน

            Console.WriteLine(“คนงานที่ {0}, เริ่มทำเนินการ phase ที่ {1}”, Task.CurrentId, barrier.CurrentPhaseNumber);
            //เริ่มกระบวนการผลิต phase ที่ 2
            Interlocked.Add(ref totalProduct, 100);
            barrier.SignalAndWait();//รอคนงานคนอื่นๆ produce phase ที่ 2 เสร็จก่อน
        };

        //ปล่อยคนทำงานแบบ Parallel ทำคนเท่ากับ Environment.ProcessorCount
        Parallel.Invoke(Enumerable.Repeat<Action>(doProduce, participantCount).ToArray());
    }

}

เมื่อ run test แล้ว console จะ print ผลออกมาได้คือ(ผลจะไม่เท่ากันนะครับขึ้นอยู่กับจำนวน Core ของ CPU)

คนงานที่ 1 เริ่มทำเนินการ phase ที่ 0
คนงานที่ 2 เริ่มทำเนินการ phase ที่ 0
คนงานทั้ง 2 คน ดำเนินการ phase ที่: 0 เสร็จสมบูรณ์, สรุป TotalProduct 200
คนงานที่ 2, เริ่มทำเนินการ phase ที่ 1
คนงานที่ 1, เริ่มทำเนินการ phase ที่ 1
คนงานทั้ง 2 คน ดำเนินการ phase ที่: 1 เสร็จสมบูรณ์, สรุป TotalProduct 400
คนงานที่ 1, เริ่มทำเนินการ phase ที่ 2
คนงานที่ 2, เริ่มทำเนินการ phase ที่ 2
คนงานทั้ง 2 คน ดำเนินการ phase ที่: 2 เสร็จสมบูรณ์, สรุป TotalProduct 600

สรุปผลจาก console ที่ print ออกมาได้ว่า ผมมีคนงาน 2 คนต่างคนก็ไปทำงาน doProduce ของตนเองไป ใน 1 งาน doProduce ก็จะแบ่งงานออกเป็น 3 phase แต่ละ phase คนงานก็จะเพิ่มผลผลิตไปทีละ 100 และเมื่อทำงานเสร็จ phase ก็ว่งสัญญานว่าเสร็จแล้ว และรอจนกระทั้งเพื่อนร่วมงานทำงานเสร็จ phsae นี้ทุกคนแล้ว เมื่อ phase สมบูรณ์ barrier ก็จะทำการสรุปเป็นรายงานผลรวมการผลิตออกมาคือ doReport นั่นเอง

ขอบคุณครับ 🙂

สมองที่สดใส มาจากร่างกายที่แข็งแรง

— ว.วชิรเมธี —

Advertisements

#net