การเปรียบเทียบ 1 <10 ราคาถูกกว่า 1 <1000000 หรือไม่


65

ฉันเพิ่งใช้จำนวนประมาณ 1 พันล้านz-indexใน CSS และคิดเกี่ยวกับการเปรียบเทียบที่ต้องดำเนินต่อไป มีความแตกต่างของประสิทธิภาพในระดับ ALU ในการเปรียบเทียบระหว่างตัวเลขขนาดใหญ่มากและเล็กมากหรือไม่?

ตัวอย่างเช่นหนึ่งในสองตัวอย่างนี้จะมีราคาแพงกว่าอีกตัวอย่างหนึ่งหรือไม่

snippet 1

for (int i = 0; i < 10000000; i++){
    if (i < 10000000000000) {
        //do nothing
    }
}

snippet 2

for (int i = 0; i < 10000000; i++){
    if (i < 1000) {
        //do nothing
    }
}

9
คุณทราบหรือไม่ว่าการทำนายสาขาทำงานอย่างไร
ริ้น

12
OP ไม่ได้ถามว่าต้องใช้เวลานานเท่าใดในการแยกสาขา ชัดเจนตัวอย่างมีไว้เพื่อให้แน่ใจว่าจะใช้เวลาเดียวกันในตัวอย่างทั้งสอง คำถามคือว่าCMPคำสั่งเครื่องแต่ละเครื่องจะช้าลงหรือไม่ถ้ายิ่งiใหญ่กว่า
Kilian Foth

18
เนื่องจากสิ่งนี้ทำใน CSS การแปลงสตริงเป็นจำนวนเต็มจะมีอิทธิพลเหนือการดำเนินการเปรียบเทียบในแง่ของเวลาที่ใช้ในการดำเนินการ

58
หากคุณต้องการใช้ 1000000000 เป็นดัชนี z ในไฟล์ CSS แสดงว่าคุณทำอะไรผิดไป
Bergi

6
สำหรับ CSS ค่าใช้จ่ายในการแปลงข้อความเป็นจำนวนเต็มจะขึ้นอยู่กับจำนวนของตัวเลขที่ถูกแปลง (ซึ่งตัวเลข 6 หลักเช่น 1000000 อาจประมาณ 6 เท่าของราคาแพงเท่ากับ 1 หลักเช่น 1) และค่าใช้จ่ายนี้อาจเป็นคำสั่งที่มีขนาดใหญ่กว่าค่าใช้จ่ายของการเปรียบเทียบจำนวนเต็ม
เบรนแดน

คำตอบ:


82

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

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

คำอธิบายของคำสั่งCMP("เปรียบเทียบ") อยู่ในเล่ม 2A หน้า 3-126 หรือหน้า 618 ของ PDF และอธิบายการทำงานเป็น:

temp ← SRC1 − SignExtend(SRC2);
ModifyStatusFlags; (* Modify status flags in the same manner as the SUB instruction*)

นี่หมายความว่าตัวถูกดำเนินการตัวที่สองจะถูกขยายสัญญาณถ้าจำเป็นลบออกจากตัวถูกดำเนินการแรกและผลลัพธ์ที่อยู่ในพื้นที่ชั่วคราวในโปรเซสเซอร์ จากนั้นแฟลกสถานะจะตั้งค่าเช่นเดียวกับที่ใช้สำหรับคำสั่งSUB("ลบ") (หน้า 1492 ของ PDF)

ไม่มีการกล่าวถึงในเอกสารCMPหรือSUBว่าค่าของตัวถูกดำเนินการมีผลต่อความล่าช้าดังนั้นค่าใด ๆ ที่คุณใช้มีความปลอดภัย


5
ถ้าจำนวนนั้นใหญ่เกินไปสำหรับเลขคณิตแบบ 32 บิตล่ะ ถ้าเช่นนั้นจะไม่ถูกแยกเป็นการคำนวณที่ช้ากว่านี้ไหม?
Falco

3
@Falco ไม่ได้อยู่ใน CPU ที่มี ALU 64 บิต (ซึ่งค่อนข้างทุกตัวยกเว้นในพื้นที่ฝังตัวในทุกวันนี้)
reirab

8
@ ฟัลโก: ใช่ แต่เนื่องจากคำถามถามเกี่ยวกับประสิทธิภาพของ ALU ความหมายก็คือว่าค่านั้นเหมาะสมกับขนาดคำของ CPU หรือความสามารถของคำสั่ง SIMD ที่อาจมี การใช้งานในจำนวนที่มากกว่านั้นจะต้องมีการใช้หลายคำสั่งนอกซีพียู นั่นเป็นเรื่องธรรมดามากเมื่อ 30 ปีที่แล้วเมื่อคุณเพิ่งลงทะเบียนทำงานกับ 8- หรือ 16- บิต
Blrfl

6
@Falco วิธีที่จะต้องแก้จุดบกพร่องหรือไม่ มันไม่ใช่ข้อผิดพลาด ช้าลงเล็กน้อยในการทำ 64-bit ops บน CPU ที่ไม่รองรับ 64-bit ops การแนะนำว่าไม่ควรใช้หมายเลขด้านบน 2 ^ 31-1 ดูเหมือนไร้สาระนิดหน่อย
reirab

2
@Falco ต้องบอกว่าเครื่องมือเรนเดอร์ในเบราว์เซอร์ใช้เลขจำนวนเต็มแทนค่าดัชนี z หรือไม่? เอนจิ้นการเรนเดอร์ส่วนใหญ่ที่ฉันคุ้นเคยกับการใช้โฟลทรีความแม่นยำเดียวสำหรับทุกสิ่ง (จนกระทั่งถึงขั้นตอนการแรสเตอร์สุดท้าย) แต่ฉันไม่ได้ศึกษาเอ็นจิ้นการเรนเดอร์เบราว์เซอร์จริงๆ
reirab

25

มีความแตกต่างของประสิทธิภาพในระดับ ALU ในการเปรียบเทียบระหว่างตัวเลขขนาดใหญ่มากและขนาดเล็กหรือไม่?

ก็ไม่น่ามากเว้นแต่ไปจากจำนวนเล็ก ๆ เป็นจำนวนมากการเปลี่ยนแปลงชนิดตัวเลขของคุณบอกว่าจากไปint longถึงอย่างนั้นความแตกต่างอาจไม่สำคัญ คุณมีแนวโน้มที่จะเห็นความแตกต่างมากขึ้นหากภาษาการเขียนโปรแกรมของคุณสลับไปเป็นเลขคณิตความแม่นยำตามอำเภอใจภายใต้หน้ากาก

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


มันควรจะกล่าวว่าตัวเลขที่นำเสนอในคำถามเป็นชนิดที่เป็นตัวเลขที่แตกต่างกันในทั่วไป 32 บิตชนิดจำนวนเต็ม ...
Falco

19

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

    cmp r0,#1      ; One-word instruction, limited to values 0-255

    cmp r0,#1000   ; Two-word instruction, limited to values 0-255 times a power of 2

    cmn r0,#1000   ; Equivalent to comparing value with -1000
                   ; Two-word instruction, limited to values 0-255 times a power of 2

    mov r1,#30000  ; Two words; can handle any value 0-65535
    cmp r0,r1      ; Could use cmn to compare to values -1 to -65535

    ldr r1,[constant1000000] ; One or two words, based upon how nearby the constant is
    cmp r0,r1
    ...

constant1000000:
    dd  1000000

รูปแบบแรกมีขนาดเล็กที่สุด รูปแบบที่สองและสามอาจหรือไม่สามารถดำเนินการได้อย่างรวดเร็วขึ้นอยู่กับความเร็วของหน่วยความจำจากรหัสที่ถูกดึง รูปแบบที่สี่จะเกือบจะช้ากว่าแบบแรกสามอย่างแน่นอนและรูปแบบที่ห้าจะช้ากว่า แต่แบบหลังสามารถใช้กับค่า 32- บิตใดก็ได้

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

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


บน MIPS คุณสามารถมี 16- บิตได้ทันทีดังนั้นการเปรียบเทียบกับ 1 จะสั้นลงและอาจเร็วกว่า 1000000 (อาจจะ) เหมือนกับ Sparc และ PowerPC และฉันคิดว่าฉันได้อ่านจากบางแหล่งว่า Intel ยังปรับการดำเนินงานให้เหมาะสมในทันทีในหลายกรณี แต่ฉันไม่แน่ใจว่าจะทำการเปรียบเทียบหรือไม่
phuclv

@ LưuVĩnhPhúc: สามารถลงทะเบียนก่อนลูป ณ จุดนั้นการเปรียบเทียบจริงจะมีจำนวนคำสั่งเท่ากันในทั้งสองกรณี
cHao

เนื่องจาก Loop เป็นเพียงตัวอย่างโดย op และคำถามคือตัวอย่าง z-index ถ้าคุณมีวัตถุ 1,000 รายการแต่ละชิ้นมีดัชนี z ของตัวเองและคุณตั้งเป็น 100000000 ... 1000000999 หรือ 10,000 ... 1,0999 และคุณวนรอบพวกเขาเพื่อจัดเรียงก่อนเรนเดอร์มีการเปรียบเทียบจำนวนมากและคำแนะนำในการโหลดมากมาย ที่นั่นมันสามารถสร้างความแตกต่าง!
Falco

@Falco: ในกรณีนี้ทันทีจะไม่ได้ปัจจัย การโหลดและเปรียบเทียบกับการลงทะเบียนดูเหมือนจะหลีกเลี่ยงไม่ได้
cHao

@cHao: หากมีการเปรียบเทียบดัชนี Z กับแต่ละอื่น ๆ พวกเขาจะอยู่ในการลงทะเบียน หากมีการจัดการดัชนีบางช่วงที่แตกต่างกันซึ่งอาจนำไปสู่การเปรียบเทียบทันที โดยทั่วไปค่าคงที่จะโหลดก่อนที่ลูปจะเริ่มต้น แต่ถ้าเช่นมีลูปที่จำเป็นในการอ่านค่าคู่จากหน่วยความจำและเปรียบเทียบค่าแรกของแต่ละคู่กับค่าคงที่ห้าค่าที่ต่างกัน ถึง 100499 และค่าอื่น ๆ ด้วยค่าคงที่เช่นนี้อีกห้าค่าอาจจะเร็วกว่ามากที่จะลบ 100250 (เก็บไว้ในทะเบียน) แล้วเปรียบเทียบกับค่า -250 ถึง 250 ...
supercat

5

คำตอบสั้น ๆ สำหรับคำถามนี้คือไม่มีไม่มีความแตกต่างเวลาในการเปรียบเทียบสองตัวเลขตามขนาดของตัวเลขเหล่านั้นโดยสมมติว่าพวกเขาเก็บไว้ในประเภทข้อมูลเดียวกัน (เช่นทั้ง 32- บิต int หรือทั้ง 64- บิตยาว)

ยิ่งไปกว่านั้นขนาดของคำว่าALUเป็นไปได้ยากอย่างไม่น่าเชื่อที่การเปรียบเทียบจำนวนเต็มสองจำนวนซึ่งกันและกันจะใช้เวลามากกว่า 1 รอบนาฬิกาเนื่องจากเป็นการดำเนินการที่ไม่สำคัญเทียบเท่ากับการลบ ฉันคิดว่าสถาปัตยกรรมทุกตัวที่ฉันเคยทำมีการเปรียบเทียบจำนวนเต็มรอบเดียว

กรณีเดียวที่ฉันนึกได้ว่าฉันพบว่าการเปรียบเทียบตัวเลขสองตัวไม่ใช่การดำเนินการรอบเดียวมีดังต่อไปนี้:

  • คำแนะนำที่มีหน่วยความจำแฝงจริงในการดึงข้อมูลตัวถูกดำเนินการ แต่ไม่มีส่วนเกี่ยวข้องกับการเปรียบเทียบตัวเอง (และโดยทั่วไปไม่สามารถทำได้ในสถาปัตยกรรม RISC แม้ว่าจะเป็นไปได้ในการออกแบบ CISC เช่น x86 / x64)
  • การเปรียบเทียบจุดลอยตัวอาจมีหลายรอบขึ้นอยู่กับสถาปัตยกรรม
  • ตัวเลขในคำถามไม่พอดีกับขนาดคำของ ALU และดังนั้นการเปรียบเทียบจะต้องแบ่งออกเป็นหลายคำแนะนำ

4

@ คำตอบของ RobertHarveyนั้นดี พิจารณาคำตอบนี้เป็นอาหารเสริมให้กับเขา


คุณควรพิจารณาการคาดคะเนสาขา :

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

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

คำถาม Stack Overflow ที่ยอดเยี่ยมในหัวข้อ


การคาดคะเนสาขาจะส่งผลต่อเวลาการแยกสาขา แต่ไม่ใช่เวลาเปรียบเทียบเอง
reirab

3

มันขึ้นอยู่กับการดำเนินการ แต่มันจะมากไม่น่ามาก

ฉันยอมรับว่าฉันยังไม่ได้อ่านรายละเอียดการใช้งานของเอนจิ้นเบราว์เซอร์ต่าง ๆ และ CSS ไม่ได้ระบุประเภทการจัดเก็บเฉพาะสำหรับตัวเลข แต่ฉันเชื่อว่ามันปลอดภัยที่จะสมมติว่าเบราว์เซอร์หลักทั้งหมดใช้ตัวเลขทศนิยมแบบ 64 บิต ("doubles" ที่มีความแม่นยำสองเท่าในการยืมคำจาก C / C ++) เพื่อจัดการกับความต้องการตัวเลขส่วนใหญ่ใน CSS เพราะนี่คือสิ่งที่ JavaScript ใช้สำหรับตัวเลขดังนั้นการใช้ชนิดเดียวกันจะทำให้การรวมง่ายขึ้น

จากมุมมองของคอมพิวเตอร์คู่ผสมทั้งหมดดำเนินการจำนวนเดียวกันของข้อมูล: 64 บิตไม่ว่าจะมีค่าเป็น 1 หรือ -3.14 หรือ 1000000 หรือ 1e100 จำนวนเวลาที่ใช้ในการดำเนินการกับตัวเลขเหล่านี้ไม่ได้ขึ้นอยู่กับมูลค่าที่แท้จริงของตัวเลขเหล่านั้นเพราะมันจะทำงานกับปริมาณข้อมูลที่เท่ากันเสมอ มีข้อเสียเปรียบในการทำสิ่งต่าง ๆ ในลักษณะนี้ซึ่งคู่นั้นไม่สามารถแสดงตัวเลขทั้งหมดได้อย่างถูกต้อง (หรือแม้กระทั่งตัวเลขทั้งหมดที่อยู่ในช่วงของพวกเขา) แต่พวกเขาสามารถเข้าใกล้ได้มากพอสำหรับเรื่องส่วนใหญ่ - ต้องการมากพอที่จะต้องการความแม่นยำมากกว่านั้น รวมสิ่งนี้เข้ากับข้อดีของความเข้ากันได้ตรงข้ามกับ JavaScript และคุณมีกรณีที่ค่อนข้างแข็งแกร่งสำหรับคู่ผสม

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

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


0

หากรหัสนี้ถูกตีความในแต่ละครั้งที่มันวิ่งมันน่าจะมีความแตกต่างกันในขณะที่มันใช้เวลานานเพื่อ tokenise และแปลความหมายเมื่อเทียบกับ10000000000000 1000อย่างไรก็ตามนี่เป็นการเพิ่มประสิทธิภาพแรกของล่ามในกรณีนี้: โทเค็นหนึ่งครั้งและแปลโทเค็น

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