เคยเขียนถึง 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