เคยเขียนถึง Altivec หรือ Velocity Engine ซึ่งเป็นตัวประมวลผลแบบเวคเตอร์ของซีพียูตระกูล Power ซึ่งนำมาใช้ใน Mac ไปแล้วรอบนึง วันนี้กำลังพัฒนาระบบขึ้นมาใช้งานใหม่ เลยอยากรู้ว่า Altivec จะทำงานได้เร็วกว่าตัวประมวลผลแบบปกติแค่ไหน เลยลองเขียนโปรแกรมหาระยะทางแบบยูคลิดดู ซึ่งถ้าเขียนแบบธรรมดาก็จะเขียนได้ง่ายๆ แบบข้างล่างนี้
float eucidean(int len, float *x, float *y) { int i; float sum=0.0; for(i=0; i<len; i++) { sum += (x[i]-y[i])*(x[i]-y[i]); } return sqrt(sum); }
โปรแกรมนี้ก็ทำงานง่ายๆ โดยเอาข้อมูลใส่ไว้ในอะเรย์แบบ float สองตัว (x กับ y) แล้วก็วนรอบคำนวณทีละตัวจนครบทุกตัว ส่วนโปรแกรมที่ทำงานแบบเวคเตอร์นั้น จะแบ่งมาคำนวณทีละ 4 ตัว ตามความสามารถของซีพียู G4 ที่ใช้อยู่ตอนนี้ เลยจะได้โปรแกรมอย่างข้างล่าง
float eucidean_altivec(int len, float *x, float *y) { int i=0,l; vector float vx,vy,vz,vsum=(vector float)vec_splat_s8(0); float sum=0.0; while(len>0) { /* Warning!!! size of float array must be divided by 4 */ vx = (vector float)vec_ld(0, x+i); vy = (vector float)vec_ld(0, y+i); vz = vec_sub(vx, vy); vsum = vec_madd(vz, vz, vsum); len -= 4; i += 4; } vsum = vec_add(vsum, vec_sld(vsum,vsum,4)); vsum = vec_add(vsum, vec_sld(vsum,vsum,8)); vec_ste(vsum, 0, &sum); return sqrt(sum); }
โปรแกรมนี้จะเริ่มจากการโหลดข้อมูลจากอะเรย์ไปเก็บไว้ในเวคเตอร์ (vx, vy) โดยใช้คำสั่ง vec_ld จากนั้นเอามาลบกันด้วย vec_sub เก็บไว้ที่ vz เสร็จแล้วก็เอายกกำลังสอง (คูณกันเอง) แล้วบวกเก็บไว้ที่ vsum สุดท้ายจะได้เวคเตอร์ที่เก็บผลรวมไว้ แต่ยังแยกเป็นสี่กลุ่ม ก็เลยเอา vsum มาเลื่อนไปมา ด้วยคำสั่ง vec_sld แล้วก็เอามาบวกกัน สุดท้ายจะได้ผลรวมอยู่ที่ตำแหน่งแรกสุด ซึ่งก็คือค่าที่ต้องการหา
ลองเทียบความเร็วด้วยการคำนวณหาระยะทางโดยให้ x และ y เป็นจุดในพื้นที่ 120 มิติ แล้วให้ทำงานหนึ่งล้านครั้ง โดยไม่มีการ optimize ตอนคอมไพล์ ได้เวลาที่แตกต่างกันเยอะพอสมควร โดยแบบธรรมดาจะใช้เวลา
real 0m4.989s user 0m4.800s sys 0m0.020s
ส่วนแบบใช้ Altivec ใช้เวลา
real 0m1.303s user 0m1.260s sys 0m0.020s
เร็วกว่าเกือบเป็นสี่เท่าเลยเนอะเนี้ย แต่ถ้ากำหนดให้สุ่มตัวเลขขึ้นมาก่อน (ด้วย rand()) ก็จะเสียเวลาไปกับการสุ่มตัวเลขซะจนไม่เห็นความแตกต่่างเลยล่ะ สรุปยังไงดีเนี้ย ..... สรุปว่าถ้าใช้เวคเตอร์ได้ก็เร็วดี แต่ว่าจะต้องเสียเวลาคิดวิธีการคำนวณใหม่ บางครั้งถ้าการคำนวณไม่ใช่จุดที่ใช้เวลาหลักของโปรแกรม การเปลี่ยนไปใช้การคำนวณเวคเตอร์ก็อาจจะไม่ให้ประโยชน์เท่าไรนัก ลองใช้พวก profiler ตรวจโปรแกรมดูก่อนก็ดี นอกจากนี้การใช้เวคเตอร์จะทำใช้โปรแกรมที่ได้ ไม่เป็นมาตรฐานเอาไปใช้บนระบบอื่นๆ ไม่ได้ ถ้าทำใช้เองก็คงจะไม่มีปัญหา แต่ถ้าคิดจะเอาไปแจกจ่ายก็คงต้องพิจารณาตรงนี้ด้วย
2 comments:
profiler คืออะไรเหรอครับ
โปรแกรมสำหรับตรวจเช็ค จับเวลา การทำงานของโปรแกรม ซึ่งจะแจกแจงให้ได้ว่า จากข้อมูลที่เราใส่เข้าไป เสียเวลาทำงานที่ ฟังก์ชันไหนเท่าไหร่ ทำให้รู้ว่าคอขวดอยู่ตรงไหน จะได้ไปแก้ที่ตรงนั้น ถ้าของ GNU ก็มี gprof (GNU Profiler)
Post a Comment