ทำไมการคูณการคูณเมทริกซ์ - เวกเตอร์ของฉันไม่


15

ขออภัยสำหรับโพสต์ที่ยาวนาน แต่ฉันต้องการรวมทุกอย่างที่ฉันคิดว่ามีความเกี่ยวข้องในครั้งแรก

สิ่งที่ฉันต้องการ

ฉันกำลังใช้ Krylov Subspace Method แบบขนานสำหรับเมทริกซ์หนาแน่น GMRES ส่วนใหญ่, QMR และ CG ฉันรู้ (หลังจากทำโปรไฟล์) ว่ารูทีน DGEMV ของฉันน่าสงสาร ดังนั้นฉันจึงตัดสินใจที่จะมีสมาธิกับมันโดยแยกมันออกมา ฉันได้ลองใช้งานด้วยเครื่อง 12 คอร์ แต่ผลลัพธ์ด้านล่างนี้สำหรับแล็ปท็อป Intel i3 แบบ 4 คอร์ แนวโน้มไม่แตกต่างกันมากนัก

ฉันKMP_AFFINITY=VERBOSEส่งออกสามารถใช้ได้ที่นี่

ฉันเขียนรหัสเล็ก ๆ :

size_N = 15000
A = randomly_generated_dense_matrix(size_N,size_N); %Condition Number is not bad
b = randomly_generated_dense_vector(size_N);
for it=1:n_times %n_times I kept at 50 
 x = Matrix_Vector_Multi(A,b);
end

ฉันเชื่อว่านี่เป็นการจำลองพฤติกรรมของ CG สำหรับการวนซ้ำ 50 ครั้ง

สิ่งที่ฉันได้ลอง:

การแปล

ฉันเคยเขียนรหัสใน Fortran ฉันแปลมันเป็น C, MATLAB และ Python (Numpy) MATLAB และ Python นั้นแย่มาก น่าแปลกที่ C นั้นดีกว่า FORTRAN ในสองหรือสองวินาทีสำหรับค่าข้างต้น เสมอต้นเสมอปลาย

โปรไฟล์

ฉันทำโปรไฟล์รหัสของฉันให้ทำงานและมันวิ่งไปไม่46.075กี่วินาที นี่คือเมื่อMKL_DYNAMIC ถูกตั้งค่าเป็นFALSEและแกนทั้งหมดถูกใช้ หากฉันใช้ MKL_DYNAMIC เป็นจริงจะมีการใช้งานเพียงประมาณครึ่งแกนในช่วงเวลาที่กำหนด นี่คือรายละเอียดบางอย่าง:

Address Line    Assembly                CPU Time

0x5cb51c        mulpd %xmm9, %xmm14     36.591s

กระบวนการที่ใช้เวลามากที่สุดน่าจะเป็น:

Call Stack                          LAX16_N4_Loop_M16gas_1
CPU Time by Utilization             157.926s
CPU Time:Total by Utilization       94.1%
Overhead Time                       0us
Overhead Time:Total                 0.0%    
Module                              libmkl_mc3.so   

นี่คือภาพบางส่วน:ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

สรุป:

ฉันเป็นผู้เริ่มต้นที่แท้จริงในการจัดทำโปรไฟล์ แต่ฉันตระหนักว่าความเร็วที่ยังไม่ดี รหัสต่อเนื่อง (1 คอร์) เสร็จสิ้นภายใน53 วินาที นั่นคือความเร็วที่น้อยกว่า 1.1!

คำถามจริง: ฉันควรทำอย่างไรเพื่อปรับปรุงการเร่งความเร็วของฉัน

สิ่งที่ฉันคิดว่าอาจช่วยได้ แต่ฉันก็ไม่แน่ใจ:

  • การใช้ Pthreads
  • การใช้งาน MPI (ScaLapack)
  • การปรับด้วยตนเอง (ฉันไม่รู้ว่าอย่างไรโปรดแนะนำทรัพยากรหากคุณแนะนำสิ่งนี้)

หากใครต้องการรายละเอียดเพิ่มเติม (โดยเฉพาะอย่างยิ่งเกี่ยวกับหน่วยความจำ) โปรดแจ้งให้เราทราบว่าฉันควรรันอะไรและอย่างไร ฉันไม่เคยทำประวัติความจำมาก่อน

คำตอบ:


20

เมทริกซ์ของคุณมีขนาด 15,000 x 15,000 ดังนั้นคุณจึงมีองค์ประกอบ 225M ในเมทริกซ์ ทำให้หน่วยความจำประมาณ 2GB นี่คือมากกว่าขนาดแคชของโปรเซสเซอร์ของคุณดังนั้นจึงต้องโหลดอย่างสมบูรณ์จากหน่วยความจำหลักในการคูณเมทริกซ์ทุกครั้งทำให้การถ่ายโอนข้อมูลประมาณ 100GB รวมทั้งสิ่งที่คุณต้องการสำหรับเวกเตอร์ต้นทางและปลายทาง

แบนด์วิดธ์หน่วยความจำสูงสุดที่มี i3 อยู่ที่ประมาณ 21 GB / s ขึ้นอยู่กับสเปคของ Intel แต่ถ้าคุณมองไปรอบ ๆ เว็บคุณจะพบว่าเกือบครึ่งหนึ่งของที่มีอยู่จริง ดังนั้นอย่างน้อยที่สุดคุณคาดหวังมาตรฐานของคุณเป็น 10 วินาทีที่ผ่านมาและการวัดจริงของคุณที่ 45 วินาทีนั้นไม่ไกลเกินกว่าเครื่องหมายนั้น

ในขณะเดียวกันคุณกำลังทำจำนวนจุดลอยตัวถึง 10 พันล้านเท่าตัวและเพิ่มเข้าไป เมื่อพิจารณาว่ารวมกัน 10 รอบนาฬิกาและอัตรานาฬิกา 3 GHz คุณจะออกมาในเวลา ~ 30 วินาที แน่นอนพวกเขาสามารถทำงานพร้อมกันกับการโหลดหน่วยความจำแบบเก็งกำไรหากแคชฉลาด

โดยรวมแล้วฉันว่าคุณอยู่ไม่ไกลจากเครื่องหมาย คุณคาดหวังอะไร


ไม่มีวิธีที่จะได้รับความเร็วอย่างน้อย 2-3 หรือไม่?
สอบถาม

@Nunoxic - คุณอาจต้องการเปรียบเทียบประสิทธิภาพหน่วยความจำในระบบของคุณโดยใช้เครื่องมือเช่น SiSoftware Sandra การวิเคราะห์ของ Wolfgangs นั้นดูดีสำหรับฉันหากแอปพลิเคชันของคุณมีแบนด์วิดท์ของหน่วยความจำที่ จำกัด การขนานจะช่วยได้เล็กน้อย ดูที่ตัวเลือกการประหยัดพลังงานที่คุณอาจมี นอกจากนี้ให้พิจารณาเปลี่ยนหน่วยความจำของคุณด้วยหน่วยความจำคุณภาพสูงตัวอย่างเช่นเวลาแฝง CAS ต่ำกว่าอาจสร้างความแตกต่างอย่างมากกับเวลาที่คุณอยู่บนกำแพง
มาร์กบูธ

4

คุณทำเมทริกซ์เวกเตอร์คูณอย่างไร? การวนซ้ำด้วยมือ? หรือโทรไปที่ BLAS? หากคุณใช้ MKL ฉันขอแนะนำอย่างยิ่งให้ใช้รูทีน BLAS ของเวอร์ชันเธรด

จากความอยากรู้คุณอาจต้องการรวบรวมATLASเวอร์ชันที่ปรับแล้วและดูว่าปัญหาดังกล่าวเกิดขึ้นได้อย่างไร

ปรับปรุง

หลังจากการสนทนาในความคิดเห็นด้านล่างปรากฎว่า Intel Core i3-330M ของคุณมีเพียงสองแกน "ของจริง" สองแกนหายไปเทิดทูนกับhyperthreading เนื่องจากในแกนที่มีเธรดมากทั้งบัสหน่วยความจำและหน่วยจุดลอยตัวจะถูกแชร์คุณจะไม่ได้รับการเร่งความเร็วหากทั้งสองอย่างนั้นเป็นปัจจัย จำกัด ในความเป็นจริงการใช้สี่แกนอาจทำให้สิ่งต่าง ๆ ช้าลง

คุณได้ผลลัพธ์แบบใดในสองแกน "เท่านั้น"


ฉันลองใช้ ATLA, GoTo และ Netlib BLAS แล้ว ทั้งหมดนั้นอ่อนแอกว่า MKL ในการแสดง นี่เป็นสิ่งที่คาดหวังหรือฉันกำลังทำอะไรผิดหรือเปล่า? ฉันรวบรวม ATLAS ตามที่กล่าวไว้ในคู่มือ นอกจากนี้ผมได้วาง (แน่นอน) รหัสของฉันที่นี่ มันเรียก BLAS ของ MKL
สอบถาม

ตกลงและสำหรับมาตราส่วนคุณแน่ใจหรือไม่ว่าในกรณีพื้นฐานของคุณรหัสนั้นทำงานบน CPU ตัวเดียวเท่านั้น เช่นถ้าคุณเปรียบเทียบมันฮิสโตแกรมการใช้งาน CPU จะแสดงเพียงแกนเดียวหรือไม่?
Pedro

ใช่. CPU ฮิสโตแกรมแสดง 1 คอร์
สอบถาม

แค่อยากรู้อีกครั้งคุณจะได้อะไรจากสองหรือสามคอร์? เครื่องของคุณไม่จริงมีสี่แกนทางกายภาพหรือเพียงแค่สองแกนกับhyperthreading ?
Pedro

ฉันจะหาสิ่งนั้นได้อย่างไร ฉันได้รวม KMP_AFFINITY ของฉันไว้ในหลักแล้ว
สอบถาม

0

ฉันรู้สึกว่าการสั่งซื้อแถวหลักเหมาะสำหรับปัญหานี้เกี่ยวกับเวลาในการเข้าถึงหน่วยความจำการใช้งานแคชของสายและการพลาด TLB ฉันเดาว่าเวอร์ชัน FORTRAN ของคุณใช้การสั่งซื้อแบบคอลัมน์เป็นหลักแทนซึ่งอาจอธิบายได้ว่าทำไมรุ่นช้ากว่ารุ่น C อย่างสม่ำเสมอ

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.