วันพฤหัสบดีที่ 9 พฤษภาคม พ.ศ. 2562

การทำงานพื้นฐานของ Multiprocessing Pool

จากบทความก่อนหน้านี้ เราได้พูดถึงข้อจำกัดของ Process ที่หากเราต้องการจะกระจายข้อมูลไปประมวลผลใน Process หลายๆตัว เพื่อลดเวลาการประมวลผล อาจทำให้เกิดปัญหาที่ข้อมูลที่ได้กลับมาอาจมีลำดับไม่ถูกต้องซึ่งเป็นผลมาจากการทำงานของ Process นั้นมีความเร็วแตกต่างกันและอาจส่งผลให้เกิดข้อผิดพลาดหากต้องนำข้อมูลไปใช้ประมวลผลต่อและต้องเป็นลำดับที่ถูกต้อง

ซึ่งจากบทความก่อนหน้าได้นำเสนอวิธีการพื้นฐานคือ การใส่ index ไปกับข้อมูลที่จะประมวลผล หลังจากทุก Process ทำงานเสร็จสิ้นให้นำผลที่ได้มาทำการเรียงโดยใช้คำสั่ง sort() ก็จะทำให้ข้อมูลกลับมาอยู่ในลำดับที่ถูกต้องอีกครั้งเนื่องจากเราทำการ sort จากค่า index นั่นเอง

นอกจากวิธีดังกล่าวแล้ว ยังมีอีกหนึ่งวิธีที่สามารถใช้ได้คือ Multiprocessing Pool

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


ภาพหลักการทำงานเบื้องต้นของ Pool

ในส่วนของการทดสอบนั้นจะใช้โค้ดคำนวณค่ากำลัง โดยทำการส่งกลุ่มของข้อมูลที่ภายในประกอบไปด้วย เลขฐานและเลขชี้กำลัง ไปคำนวณผ่านการใช้ Pool

import multiprocessing as mp
import threading
import os

# use to delay time and check CPU core
loop = 10000000

def power(data_array):

     print("PID: %s, Process Name: %s, Thread Name: %s" % (
       os.getpid(),
       mp.current_process().name,
       threading.current_thread().name))

     num = data_array[0]
     degree = data_array[1]

     for i in range(loop):
          result = 1
          if degree%2 == 0 :
               for i in range( int(degree/2) ):
                    result = result*num
               result = result*result
          elif degree%2 != 0 :
               for i in range( int(degree/2) ):
                    result = result*num
               result = result*result*num

     print("%s to the power %s is %s" %(num,degree,result))
     print("Process Name: %s Finish." % (mp.current_process().name))

     return result

def main():

     array = [[2,2], [2,3], [2,4], [2,5]]
     NUM_WORKER = mp.cpu_count()/2

     # creating pool
     pool = mp.Pool(NUM_WORKER)

     # map the function to each data in array
     result = pool.map(power, array)

     # close pool and wait until all processes are finished
     pool.close()
     pool.join()
     print("Pool result : %s" % result)

if __name__ == "__main__":
     main()

ซึ่งได้ผลลัพธ์ดังนี้


ภาพผลลัพธ์การทำงานของ Pool


ภาพการทำงานของ CPU Core

จาก Input ที่ป้อนเข้าไปเป็นฐาน 2 และเลขกำลัง 2, 3, 4 และ 5 ตามลำดับ ซึ่งจากภาพจะพบว่าค่ากำลังที่ pool return กลับมาให้นั้นตรงตามที่เราต้องการคือ 4, 8, 16 และ 32 อีกทั้งถึงแต่ละ process จะเสร็จไม่ตามลำดับแต่ผลที่ให้กลับมาก็เรียงลำดับอย่างถูกต้องเช่นกัน

ไม่มีความคิดเห็น:

แสดงความคิดเห็น