การใช้งาน BLAS รับประกันว่าจะให้ผลลัพธ์ที่แน่นอนหรือไม่


17

ด้วยการใช้งาน BLAS สองแบบที่แตกต่างกันเราคาดหวังได้หรือไม่ว่าพวกเขาทำการคำนวณจุดลอยตัวที่แน่นอนและกลับผลลัพธ์เดียวกัน หรือสามารถเกิดขึ้นได้เช่นหนึ่งคำนวณผลิตภัณฑ์สเกลาร์เป็น และอีกหนึ่งเป็น ( x 1 y 1 + x 2 y 2 ) + ( x 3 y 3 + x 4

((x1Y1+x2Y2)+x3Y3)+x4Y4
ดังนั้นอาจจะให้ผลที่แตกต่างกันใน IEEE ลอยคำนวณจุด?
(x1Y1+x2Y2)+(x3Y3+x4Y4),

1
มีข้อร้องเรียนเกี่ยวกับคุณภาพ BLAS ในชุดข้อความนี้ค้นหา CBLAS ในหน้านี้ ที่จะแนะนำว่าพวกเขาไม่เพียง แต่ให้ผลลัพธ์ที่เหมือนกัน แต่ไม่ทั้งหมดที่ถูกต้องเพียงพอสำหรับงานใด ๆ ...
Szabolcs

คำตอบ:


15

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

ใน NETLIB BLAS ผลิตภัณฑ์เซนต์คิตส์และเนวิสเป็นเพียงการวนซ้ำที่ไม่ได้ควบคุมโดยปัจจัย 5:

DO I = MP1,N,5
          DTEMP = DTEMP + DX(I)*DY(I) + DX(I+1)*DY(I+1) +
     $            DX(I+2)*DY(I+2) + DX(I+3)*DY(I+3) + DX(I+4)*DY(I+4)
END DO

และมันก็ขึ้นอยู่กับคอมไพเลอร์ถ้าการเพิ่มการคูณแต่ละครั้งลงใน DTEMP ทันทีหรือถ้าส่วนประกอบทั้งหมด 5 ตัวถูกรวมกันก่อนแล้วจึงเพิ่มเข้าไปใน DTEMP ใน OpenBLAS มันขึ้นอยู่กับสถาปัตยกรรมเคอร์เนลที่ซับซ้อนมากขึ้น:

 __asm__  __volatile__
    (
    "vxorpd     %%ymm4, %%ymm4, %%ymm4               \n\t"
    "vxorpd     %%ymm5, %%ymm5, %%ymm5               \n\t"
    "vxorpd     %%ymm6, %%ymm6, %%ymm6               \n\t"
    "vxorpd     %%ymm7, %%ymm7, %%ymm7               \n\t"

    ".align 16                           \n\t"
    "1:                          \n\t"
        "vmovups                  (%2,%0,8), %%ymm12         \n\t"  // 2 * x
        "vmovups                32(%2,%0,8), %%ymm13         \n\t"  // 2 * x
        "vmovups                64(%2,%0,8), %%ymm14         \n\t"  // 2 * x
        "vmovups                96(%2,%0,8), %%ymm15         \n\t"  // 2 * x

    "vmulpd      (%3,%0,8), %%ymm12, %%ymm12 \n\t"  // 2 * y
    "vmulpd    32(%3,%0,8), %%ymm13, %%ymm13 \n\t"  // 2 * y
    "vmulpd    64(%3,%0,8), %%ymm14, %%ymm14 \n\t"  // 2 * y
    "vmulpd    96(%3,%0,8), %%ymm15, %%ymm15 \n\t"  // 2 * y

    "vaddpd      %%ymm4 , %%ymm12, %%ymm4 \n\t"  // 2 * y
    "vaddpd      %%ymm5 , %%ymm13, %%ymm5 \n\t"  // 2 * y
    "vaddpd      %%ymm6 , %%ymm14, %%ymm6 \n\t"  // 2 * y
    "vaddpd      %%ymm7 , %%ymm15, %%ymm7 \n\t"  // 2 * y

    "addq       $16 , %0	  	     \n\t"
	"subq	        $16 , %1            \n\t"      
    "jnz        1b                   \n\t"
...

ซึ่งแยกผลิตภัณฑ์สเกลาร์ออกเป็นผลิตภัณฑ์สเกลาร์ขนาดเล็กที่มีความยาว 4 และรวมเข้าด้วยกัน

การใช้การใช้งาน BLAS ทั่วไปอื่น ๆ เช่น ATLAS, MKL, ESSL, ... ปัญหานี้ยังคงเหมือนเดิมเพราะการใช้งาน BLAS แต่ละครั้งจะใช้การปรับแต่งที่แตกต่างกันเพื่อรับโค้ดที่รวดเร็ว แต่เท่าที่ฉันรู้จำเป็นต้องมีตัวอย่างเทียมเพื่อให้ได้ผลลัพธ์ที่ผิดพลาดจริงๆ

หากจำเป็นต้องให้ไลบรารี BLAS ส่งคืนผลลัพธ์เดียวกัน (บิตที่ชาญฉลาดเหมือนกัน) จะต้องใช้ไลบรารี BLAS ที่ทำซ้ำได้เช่น:


8

คำตอบสั้น ๆ

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

อย่างไรก็ตามมีหลายสิ่งที่สามารถทำลายพฤติกรรมนี้เพื่อประสิทธิภาพ ...

คำตอบอีกต่อไป

IEEE ยังระบุลำดับที่การดำเนินการเหล่านี้ดำเนินการนอกเหนือไปจากการดำเนินการแต่ละอย่าง อย่างไรก็ตามหากคุณรวบรวมการใช้ BLAS ด้วยตัวเลือกเช่น "-ffast-math" คอมไพเลอร์สามารถทำการแปลงที่จะเป็นจริงในเลขคณิตที่แน่นอน แต่ไม่ "ถูกต้อง" ใน IEEE ตัวอย่างที่ยอมรับได้คือการไม่เชื่อมโยงของการเพิ่มจุดลอยตามที่คุณชี้ให้เห็น ด้วยการตั้งค่าการเพิ่มประสิทธิภาพที่ก้าวร้าวมากขึ้นการเชื่อมโยงจะถูกสันนิษฐานและโปรเซสเซอร์จะทำสิ่งนั้นมากในแบบขนานเท่าที่จะทำได้โดยการสั่งซื้อการดำเนินการอีกครั้ง

a+* * * *


3
"ตลาดน้ำคำนวณจุดไม่ได้สุ่ม" เป็นเรื่องน่าเศร้าที่จะต้องมีการระบุไว้อย่างชัดเจน แต่ดูเหมือนว่าคนจำนวนมากเกินไปคิดว่าเป็น ...
pipe

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

@TylerOlsen นี่ไม่เกี่ยวข้องกับคำถามและนี่ไม่ใช่เหตุผลที่คลาสเหล่านั้นพูดถึงสิ่งต่าง ๆ แต่ IIRC นั้นเคยเป็นคลาสของคอมไพเลอร์บั๊กซึ่งไม่สามารถพึ่งพาความเท่าเทียมกันได้ เช่นบางครั้งif (x == 0) assert(x == 0) อาจล้มเหลวซึ่งจากมุมมองที่แน่นอนจะดีเท่าการสุ่ม
คิริลล์

@ คิริลขออภัยฉันแค่พยายามทำให้ถึงจุดที่หลาย ๆ คนไม่เคยเรียนรู้ว่าจุดลอยทำงานอย่างไร สำหรับประเด็นทางประวัติศาสตร์นั้นเป็นเรื่องที่น่ากลัว แต่ก็ต้องได้รับการแก้ไขก่อนที่ฉันจะเข้าสู่เกม
Tyler Olsen

@TylerOlsen โอ๊ะโอตัวอย่างของฉันผิด มันควรจะเป็นif (x != 0) assert(x != 0)เพราะเลขคณิตที่มีความแม่นยำเพิ่มขึ้น
คิริลล์

4

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

มีความพยายามบางอย่างในการรับการประยุกต์ใช้ BLAS ที่ทำซ้ำได้ ดูReproBLASและExBLASสำหรับข้อมูลเพิ่มเติม


1
ดูเพิ่มเติมที่คุณลักษณะการทำซ้ำตัวเลขเชิงเงื่อนไข (CNR) ใน MKL BLAS รุ่นล่าสุดของ Intel ตระหนักว่าการได้รับความสามารถในการทำซ้ำในระดับนี้มักจะทำให้การคำนวณของคุณช้าลงและอาจทำให้ช้าลงมาก!
Brian Borchers
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.