เหตุใดนักวิทยาศาสตร์การคำนวณจึงจำเป็นต้องใช้ std :: complex เวอร์ชันของตนเอง?


14

ไลบรารี C ++ ที่เป็นที่รู้จักมากขึ้นในด้านวิทยาศาสตร์การคำนวณเช่นEigen , Trilinosและdeal.IIใช้วัตถุไลบรารีส่วนหัวเทมเพลต C ++ มาตรฐานstd::complex<>เพื่อแทนจำนวนจุดลอยตัวที่ซับซ้อน

ในคำตอบของ Jack Poulson สำหรับคำถามเกี่ยวกับ Constructor เริ่มต้นเขาชี้ให้เห็นว่าเขามีการนำไปใช้std::complexในElementalของตนเองด้วยเหตุผลหลายประการ อะไรคือเหตุผลเหล่านั้น อะไรคือข้อดีและข้อเสียของวิธีนี้?

คำตอบ:


16

ฉันเชื่อว่าการสนทนานี้เกิดขึ้นหลายครั้งในรายการ PETSc เหตุผลหลักของฉันคือ:

  1. สถานะมาตรฐาน C ++ ที่ std :: complex ได้รับการกำหนดสำหรับประเภทข้อมูล float, double และ long double เท่านั้น ดังนั้นจึงไม่สามารถใช้กับประเภทข้อมูลอื่น ๆ เช่นความแม่นยำของรูปสี่เหลี่ยม

  2. มาตรฐานไม่รับประกันเกี่ยวกับความเสถียรของเลขคณิตที่ซับซ้อน

  3. มาตรฐานไม่รับประกันว่าข้อมูลใน std :: complex จะถูกจัดเก็บเป็นองค์ประกอบจริงตามด้วยองค์ประกอบจินตภาพ สิ่งนี้มีความสำคัญสำหรับส่วนต่อประสานกับไลบรารีภายนอกเช่น BLAS และ LAPACK มันเป็นความจริงสำหรับการใช้งานที่สำคัญทั้งหมด แต่ฉันต้องการที่จะมั่นใจได้

  4. ฉันชอบความสามารถในการจัดการองค์ประกอบจริงและจินตภาพโดยตรง std :: complex ทำให้ยากโดยไม่จำเป็น

  5. ในที่สุดฉันก็อยากจะมีรุ่นทั่วไปมากขึ้นซึ่งต้องการเพียงประเภทข้อมูลที่จะเป็นแหวนแทนที่จะต้องมีเขตข้อมูล ซึ่งจะรวมถึงจำนวนเต็ม Gaussian


6
จุดที่ 3 ได้รับการแก้ไขใน C ++ 11 26.4.4 ระบุว่าหากzคือการแสดงออก lvalue ชนิดพันธุ์ std::complex<T>แล้วreinterpret_cast<cv T(&)[2]>(z)และreinterpret_cast<cv T(&)[2]>(z)[0]จะกำหนดส่วนที่แท้จริงของzและจะกำหนดส่วนจินตภาพของreinterpret_cast<cv T(&)[2]>(z)[1] zอาร์เรย์ของตัวเลขที่ซับซ้อนจะได้รับการแก้ไขด้วย
James Custer

3
@ JamesCuster: ในที่สุดฉันก็เปลี่ยนมาใช้ C ++ 11 แต่รหัสทางวิทยาศาสตร์ที่ต้องการให้พกพาไปยังสถาปัตยกรรมกึ่งแปลกใหม่อาจต้องรออย่างน้อยสองถึงสามปีจึงจะทำได้ นอกจากนี้ C ++ 11 โชคไม่ดีที่อยู่เพียงส่วนหนึ่งของปัญหา
Jack Poulson

ฉันเข้าใจว่าฉันเพิ่งโยนมันทิ้งไปในกรณีที่มีคนดูคำถามนี้ในอนาคต
James Custer

2
ฉันคิดว่ามันเป็นทางออกที่ต้องบอกว่าคุณต้องรอจนกว่าคอมไพเลอร์จะสนับสนุน C ++ 11 ข้อกำหนดที่ชัดเจนถูกนำไปใช้กับมาตรฐานใหม่เนื่องจากการใช้งานที่มีอยู่ทั้งหมดสนับสนุนแล้ว ฉันไม่สามารถนึกถึงกรณีที่ไม่ปลอดภัยที่จะถือว่าโครงร่างนี้เฉพาะในคอมไพเลอร์ / ไลบรารีที่มีอยู่แล้วเนื่องจากมันไม่เหมาะสมที่จะใช้ std :: complex ด้วยวิธีอื่น
Wolfgang Bangerth

1
@ WolfgangBangerth: มันเป็นความคิดเห็นทั่วไปเพิ่มเติมเกี่ยวกับการเปลี่ยนเป็น C ++ 11 อย่างไรก็ตาม C ++ 11 ไม่สามารถแก้ไขปัญหาส่วนใหญ่ของ std :: complex ได้
Jack Poulson

7

ฉันใช้std::complex<>ในโปรแกรมของฉันและต้องต่อสู้กับธงคอมไพเลอร์และวิธีแก้ปัญหาสำหรับคอมไพเลอร์ใหม่หรืออัพเกรดคอมไพเลอร์ ฉันจะพยายามนับการต่อสู้เหล่านี้ตามลำดับเวลา:

  1. std::norm|z|2|z|-ffast-math
  2. คอมไพเลอร์ intel icc บน linux (หรือตัวลิงก์) ที่คอมไพล์แล้วstd::argไปยังตัวเลือกที่ไม่ใช้ภายใต้การกำหนดค่าบางอย่าง ปัญหาเกิดซ้ำบ่อยเกินไปดังนั้นจึงstd::argต้องถูกแทนที่ด้วย atan2(imag(),real())แต่มันง่ายเกินไปที่จะลืมสิ่งนี้เมื่อเขียนรหัสใหม่
  3. ชนิดนี้std::complexใช้ระเบียบการโทรที่แตกต่างกัน (= ABI) กว่าประเภทคอมเพล็กซ์ในตัว C99 และประเภทคอมเพล็กซ์ Fortran ในตัวสำหรับรุ่น gcc ที่ใหม่กว่า
  4. การ-ffast-mathคอมไพล์ธงทำปฏิกิริยากับการจัดการข้อยกเว้นจุดลอยตัวในวิธีที่ไม่คาดคิด สิ่งที่เกิดขึ้นคือคอมไพเลอร์ดึงหน่วยงานออกจากลูปจึงทำให้เกิดdivision by zeroข้อยกเว้นในขณะทำงาน ข้อยกเว้นเหล่านี้จะไม่เกิดขึ้นภายในลูปเนื่องจากส่วนที่เกี่ยวข้องไม่ได้เกิดขึ้นเนื่องจากตรรกะโดยรอบ อันนั้นแย่มากเพราะเป็นห้องสมุดที่รวบรวมแยกต่างหากจากโปรแกรมที่ใช้การส่งข้อยกเว้นจุดลอยตัว (ใช้ธงคอมไพล์ที่แตกต่างกัน) และพบปัญหาเหล่านี้ (ทีมที่เกี่ยวข้องกำลังนั่งอยู่ตรงข้ามส่วนหนึ่งของโลก) ปัญหานี้ทำให้เกิดปัญหาที่เลวร้ายจริงๆ) สิ่งนี้แก้ไขได้ด้วยการเพิ่มประสิทธิภาพที่คอมไพเลอร์ใช้ด้วยมืออย่างระมัดระวังมากขึ้น
  5. ไลบรารีกลายเป็นส่วนหนึ่งของโปรแกรมและไม่ใช้-ffast-mathแฟล็กการคอมไพล์อีกต่อไป หลังจากอัปเกรดเป็น gcc รุ่นใหม่ประสิทธิภาพจะลดลงตามปัจจัยที่มีขนาดใหญ่ ฉันยังไม่ได้ตรวจสอบปัญหานี้ในรายละเอียด แต่ฉันกลัวว่ามันจะเกี่ยวข้องกับC99 ภาคผนวก G ฉันต้องยอมรับว่าฉันสับสนอย่างสมบูรณ์โดยคำจำกัดความที่แปลกประหลาดของการคูณสำหรับจำนวนเชิงซ้อนและดูเหมือนว่ามีอยู่ในรุ่นที่แตกต่างกันของเรื่องนี้โดยอ้างว่ารุ่นอื่นเข้าใจผิด ฉันหวังว่าการ-fcx-limited-rangeรวบรวมการตั้งค่าสถานะจะแก้ปัญหาได้เนื่องจากมีปัญหาอื่นที่เกี่ยวข้องกับ-ffast-mathรุ่น gcc ที่ใหม่กว่านี้
  6. การ-ffast-mathคอมไพล์แฟล็กทำให้พฤติกรรมNaNไม่สามารถคาดเดาได้อย่างสมบูรณ์สำหรับ gcc รุ่นใหม่ (แม้isnanจะได้รับผลกระทบ) วิธีแก้ปัญหาเท่านั้นดูเหมือนว่าจะหลีกเลี่ยงการเกิดใด ๆในโปรแกรมซึ่งขัดแย้งกับวัตถุประสงค์สำหรับการดำรงอยู่ของNaNNaN

ตอนนี้คุณอาจถามว่าฉันวางแผนที่จะละทิ้งประเภทที่ซับซ้อนในตัวและstd::complexด้วยเหตุผลเหล่านี้ ฉันจะอยู่กับประเภทในตัวตราบใดที่ฉันยังคงอยู่กับ C ++ ในกรณีที่ C ++ ควรจัดการให้ใช้ไม่ได้อย่างสมบูรณ์สำหรับการคำนวณทางวิทยาศาสตร์ฉันจะพิจารณาเปลี่ยนไปใช้ภาษาที่ดูแลปัญหาที่เกี่ยวข้องกับการคำนวณทางวิทยาศาสตร์มากขึ้น


ดูเหมือนความกลัวของฉันเกี่ยวกับ C99 Annex G เป็นจริงขึ้นมาและช่วง -fcx-limited- เป็นสิ่งที่จำเป็นสำหรับความเร็วในการคำนวณที่ดีเมื่อคูณจำนวนเชิงซ้อน อย่างน้อยนั่นคือสิ่งที่ฉันได้รับจากเรื่องราวสงครามเมื่อไม่นานมานี้: medium.com/@smcallis_71148/…
Thomas Klimpel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.