Posted by Revolution
Thu, 04 Sep 2008 16:29:00 GMT
จากครั้งที่แล้วผมอยากจะเขียน ruby สักอันไว้ทำการ stamp ลายเซ็นพร้อมค่า exif ลงในรูป จากการลองเขียนเป็น thread แล้วปรากฏว่าไม่ค่อยมีประโยชน์เท่าไหร่กลับกลายเป็นว่ามี overhead ขึ้นมาเพียบและก็ทำงานไม่ครบได้ทุก core ที่มี งานส่วนใหญ่ในการทำงานเกี่ยวกับภาพนี่จะเป็นในด้านคำนวนซะเยอะ เลยเขียนเป็นลักษณะ fork ออกมาจะดีกว่า
พอลองได้เขียนก็ได้แนวคิดมา 2 แบบ คือ
- ทำงานแบบเป็น lot คือทำพร้อมกันที่ละเท่าๆกัน แล้วรอให้เสร็จหมด ค่อยเริ่ม lot ต่อไป แบบนี้ถ้ามี process ใน lot เสร็จก่อนเพื่อนก็ต้องรอ
- แบบที่สองคือเริ่มทำงานให้เต็มตามที่เรากำหนด ถ้า process ไหนเสร็จก่อนก็เอา process ใหม่มา run ได้เลย แบบนี้จะทำให้การทำงานต่อเนื่อง
แบบนี้คือการทำงานแบบเป็น Lot
NUMFORK = 2
getImg = Dir['*.jpg','*.JPG','*.Jpg','*.jpeg'].sort.reverse
Dir.mkdir("stamped") if !File.exist?("stamped")
numFork = 0
while !getImg.empty?
numFork = numFork + 1
photo = getImg.pop
Process.fork{stampit(photo)}
if numFork == NUMFORK
Process.waitall
numFork = 0
end
end
Process.waitall
ส่วนแบบนี้คือการทำงานแบบต่อเนื่อง
NUMFORK = 2
getImg = Dir['*.jpg','*.JPG','*.Jpg','*.jpeg'].sort.reverse
Dir.mkdir("stamped") if !File.exist?("stamped")
numFork = 0
while !getImg.empty?
numFork = numFork + 1
photo = getImg.pop
Process.fork{stampit(photo)}
if numFork >= NUMFORK
Process.wait
numFork = numFork - 1
end
end
Process.waitall
อย่างนี้ก็สบายใช้งานคุ้มทุก core
Posted in ruby, linux | Tags fork, photo, process, ruby, thread | no comments | no trackbacks
Posted by Revolution
Wed, 03 Sep 2008 16:57:00 GMT
คือว่าผมใช้ debian + ruby + rmagick เขียน script เพื่อที่จะทำการ stamp รูป แต่มาได้ความคิดว่า อย่าง convert เนี่ย ถ้าเราเรียก
$ convert -resize 1600 *.jpg
มันจะใช้ cpu 1 core เต็มๆ แต่อีก core จะชิวๆ หรือไม่ทำงานยุ่งเกี่ยวกับ convert เลย ก็เลยลองให้มันทำ
$ convert -resize 1600 *[02468].jpg &
$ convert -resize 1600 *[13579].jpg &
ผลลัพท์ที่ได้คือมันใช้ 2 core ทำงาน เป็นเพราะ shell เรียก convert นี่เป็น native ซึ่งมันจะไปทำงานแบบ fork จึงได้ผลลัพทธ์ดังกล่าว
จากที่อ่านมา Fork คือ Heavy Weight Process ที่แยก resource กันชัดเจน ส่วน Thread คือ Light Weight Process ที่แบ่งปัน resource ซึ่งกันและกัน
แต่ปัญหาอยู่ที่ว่าคือผมเขียน ruby คิดว่าถ้ามันเป็น thread ก็จะน่าได้ผลลัพธ์เช่นเดียวกับการ fork 2 ครั้ง แต่ผลลัพธ์ที่ได้กลับกลายเป็นว่า การทำงานนั้นไม่เต็ม 2 core คือใช้เพียงแค่ 1 core เท่านั้น
จากการศึกษาเพิ่มเติมได้ผลออกมาว่า thread นั้นมี 2 แบบคือ user space และ kernel space
- Kernel space จะเป็น thread แบบ native คือ kernel จะเป็นผู้จัดสรรและสับเปลี่ยน ก็จะได้ประสิทธิภาพตามคุณภาพของ kermel + cpu
- User space หรือเรียกอีกอย่างว่า Green thread คือ thread ที่ทำงานแบบ time slice โดยผู้รับผิดชอบคือ VM (Virtual Machine) ในกรณีของผมคือ ruby นั่งเอง VM จะทำหน้าที่จัดสรรและสับเปลี่ยน เสหมือนเป็นการจำลอง thread อีกที ผลที่ได้คือ kernel เห็นเป็นเพีบง singel thread จึงทำงานได้เต็มที่แค่ 1 core
สรุปได้ว่า thread บน ruby นั้นป็น green thread จึงได้ผลลัพธ์ดังกล่าว ทางแก้ตอนนี้คือเขียนให้ ruby นั้น fork อีก process
ไม่ใช่ว่า ruby thread จะไม่มีประโยชน์ ไว้จะลองเขียน ประโยชน์ของ ruby thread ดู
Posted in ruby, linux | Tags convert, fork, imagemagick, kernel, rmagick, ruby, thread | no comments | no trackbacks