ตัวเลขจุดลอยตัวแบบแข็งและแบบอ่อนต่างกันอย่างไร


99

เมื่อฉันคอมไพล์โค้ด C ด้วย cross toolchain ตัวเชื่อมโยงจะพิมพ์หน้าคำเตือนโดยบอกว่าไฟล์ปฏิบัติการของฉันใช้ฮาร์ดโฟล แต่ libc ของฉันใช้ซอฟต์โฟล อะไรคือความแตกต่าง?


หากเป็นสถาปัตยกรรม ARM โปรดใส่ลงในแท็ก :-)
Nils Pipenbrinck

3
@Nils Pipenbrinck: ชิป MIPS ก็มีปัญหานี้เช่นกัน
Javier

คำตอบ:


101

การลอยตัวแบบแข็งใช้หน่วยจุดลอยตัวบนชิป ซอฟท์ลอยจำลองหนึ่งในซอฟต์แวร์ ความแตกต่างคือความเร็ว เป็นเรื่องแปลกที่เห็นทั้งคู่ใช้กับสถาปัตยกรรมเป้าหมายเดียวกันเนื่องจากชิปมี FPU หรือไม่ คุณสามารถเปิดใช้งานจุดลอยตัวอ่อนใน GCC ด้วย -msoft-float คุณอาจต้องการคอมไพล์ libc ของคุณใหม่เพื่อใช้จุดลอยตัวของฮาร์ดแวร์หากคุณใช้


3
"เป็นเรื่องแปลกที่เห็นทั้งสองอย่างถูกใช้ในสถาปัตยกรรมเป้าหมายเดียวกัน" สิ่งนี้อาจทำให้รู้สึกว่าไลบรารีเป็นแบบไม่ขึ้นกับเครื่องและแบบบิต (soft float) ในชิ้นส่วนที่มีความแม่นยำและรวดเร็ว (hard float) ในส่วนที่มีการเบี่ยงเบนเล็กน้อย ไม่สำคัญ
PhilLab

มันเกิดขึ้นบน ARM 32 บิต
Aaron Franke

31

มีสามวิธีในการคำนวณเลขคณิตลอยตัว:

  • ใช้คำแนะนำแบบลอยหาก CPU ของคุณมี FPU (เร็ว)
  • ให้คอมไพเลอร์ของคุณแปลเลขคณิตทศนิยมเป็นเลขคณิตจำนวนเต็ม (ช้า)
  • ใช้คำแนะนำลอยและ CPU ที่ไม่มี FPU CPU ของคุณจะสร้างข้อยกเว้น (Reserved Instruction, Unimplemented Instruction หรือ similar) และหากเคอร์เนลระบบปฏิบัติการของคุณมีตัวจำลองจุดลอยตัวก็จะเลียนแบบคำสั่งเหล่านั้น (ช้าที่สุด)

23

พูดอย่างเคร่งครัดคำตอบทั้งหมดนี้ดูเหมือนจะผิดสำหรับฉัน

เมื่อฉันคอมไพล์โค้ด C ด้วย cross toolchain ตัวเชื่อมโยงจะพิมพ์หน้าคำเตือนโดยบอกว่าไฟล์ปฏิบัติการของฉันใช้ฮาร์ดโฟล แต่ libc ของฉันใช้ซอฟต์โฟล อะไรคือความแตกต่าง?

Debian VFP วิกิพีเดียมีข้อมูลเกี่ยวกับทางเลือกที่สามสำหรับ-mfloat-abi,

  • soft - นี่คือซอฟต์แวร์ที่แท้จริง
  • softfp- รองรับฮาร์ดแวร์ FPU แต่ABIเข้ากันได้กับซอฟต์
  • hard- ABI ใช้การลงทะเบียนแบบลอยหรือVFP

ข้อผิดพลาดตัวเชื่อมโยง (ตัวโหลด) เป็นเพราะคุณมีไลบรารีที่ใช้ร่วมกันซึ่งจะส่งผ่านค่าทศนิยมในการลงทะเบียนจำนวนเต็ม คุณยังสามารถคอมไพล์โค้ดของคุณด้วย a -mfpu=vfpและอื่น ๆ ได้ แต่คุณควรใช้-mfloat-abi=softfpเพื่อที่ว่าหากlibcต้องการ float มันจะถูกส่งผ่านไปในลักษณะที่ไลบรารีเข้าใจ

เคอร์เนล Linux สามารถรองรับการจำลองคำสั่ง VFP เห็นได้ชัดว่าคุณควรคอมไพล์-mfpu=noneสำหรับกรณีนี้และให้คอมไพล์สร้างโค้ดโดยตรงแทนที่จะใช้การจำลองเคอร์เนลของ Linux อย่างไรก็ตามฉันไม่เชื่อว่าข้อผิดพลาดของ OP เกี่ยวข้องกับปัญหานี้จริงๆ -mfloat-abiมันเป็นแยกต่างหากและยังต้องจัดการกับพร้อมกับ

ไลบรารีที่ใช้ร่วมกันของ Armv5 กับ ArmV7 CPUนั้นตรงกันข้ามกับไลบรารีนี้ libcเป็นลอยยาก แต่การประยุกต์ใช้เป็นเพียงที่อ่อนนุ่ม มีบางวิธีในการแก้ไขปัญหา แต่การคอมไพล์ใหม่ด้วยตัวเลือกที่ถูกต้องนั้นง่ายที่สุดเสมอ

อีกปัญหาหนึ่งคือเคอร์เนล Linux ต้องรองรับงาน VFP (หรือจุดลอยตัวของ ARM) เพื่อบันทึก / เรียกคืนรีจิสเตอร์บนสวิตช์บริบท


1
เวอร์ชัน GCC สมัยใหม่ (~ 4.8 +) รองรับ 'multi-lib' ซึ่งมีไลบรารีแบบฮาร์ดโฟลตและซอฟต์โฟลต เวอร์ชันก่อนหน้านี้คุณต้องมีคอมไพเลอร์ที่สร้างขึ้นด้วยเวอร์ชันเฉพาะ ในบางครั้งจำเป็นต้องใช้พา ธ ไปยังไลบรารีที่ถูกต้องเมื่อเชื่อมโยงกับการแจกจ่าย gcc 'multi-lib' เนื่องจากมีไลบรารีหลายเวอร์ชัน (ต้องใช้เวลาในการสร้างคอมไพเลอร์นานขึ้น) ชื่อไดเร็กทอรีอาจเป็น "hf", "hardf", "libhf" หรือ "hard-float" แต่โดยปกติแล้วจะอยู่ภายใต้ไดเร็กทอรี "soft" หรือตำแหน่งใกล้เคียง
ไร้เสียงรบกวน

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

13

ดูเหมือนว่า libc ของคุณถูกสร้างขึ้นสำหรับการดำเนินการจุดลอยตัวของซอฟต์แวร์ในขณะที่ exe ของคุณถูกคอมไพล์โดยสมมติว่ารองรับฮาร์ดแวร์สำหรับจุดลอยตัว ในระยะสั้นคุณสามารถบังคับให้ soft float เป็นแฟล็กคอมไพเลอร์ (ถ้าคุณใช้ gcc ฉันคิดว่ามันเป็น -msoft-float)

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


8

การคำนวณอาจทำได้โดยใช้ฮาร์ดแวร์ทศนิยมหรือในซอฟต์แวร์โดยใช้เลขคณิตจำนวนเต็ม

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

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

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