การเปรียบเทียบโดยตรงครั้งแรก
ฉันจะเริ่มต้นด้วยรหัสที่สอดคล้องกันมากกับรหัส Python ของคุณมากกว่าการแปลของคุณเอง ฉันคิดว่ารหัส Raku ที่เทียบเท่าโดยตรงกับ Python ของคุณมากที่สุดคือ:
my \table = [ [ 0 for ^4000 ] for ^4000 ];
say table[3999;3999]; # 0
รหัสนี้ประกาศตัวระบุเครื่องหมายฟรี1 มัน:
วาง "รูปร่าง" ( [4000;4000]
ในmy @table[4000;4000]
) ฉันทำผิดเพราะรหัส Python ของคุณไม่ได้ทำ การสร้างฟาโรห์ให้ประโยชน์ แต่มีผลกระทบด้านประสิทธิภาพ 2
การใช้งานที่มีผลผูกพันแทนการที่ได้รับมอบหมาย ฉันเปลี่ยนมาใช้การผูกเพราะรหัส Python ของคุณกำลังทำการผูกไม่ใช่การมอบหมาย (Python ไม่ได้แยกความแตกต่างระหว่างทั้งสอง) ในขณะที่วิธีการมอบหมายของ Raku นำข้อดีพื้นฐานที่ควรค่าแก่การใช้รหัสทั่วไปมาใช้ 3
รหัสนี้ฉันได้เริ่มตอบด้วยยังช้า
อันดับแรกรหัส Raku ทำงานผ่านคอมไพเลอร์ Rakudo ตั้งแต่เดือนธันวาคม 2018 ช้ากว่ารหัส Python ของคุณประมาณ 5 เท่าโดยใช้ Python interpreter ตั้งแต่เดือนมิถุนายน 2019 บนฮาร์ดแวร์เดียวกัน 3
ประการที่สองทั้งรหัส Raku และรหัส Python ช้าเช่นเปรียบเทียบกับรหัส C # ของคุณ เราทำได้ดีกว่า ...
ทางเลือกที่ใช้สำนวนที่เร็วกว่าพันเท่า
รหัสต่อไปนี้มีมูลค่าการพิจารณา:
my \table = [ [ 0 xx Inf ] xx Inf ];
say table[ 100_000; 100_000 ]; # 0
แม้จะมีรหัสนี้สอดคล้องกับอาร์เรย์องค์ประกอบหนึ่งล้านล้านไม่ใช่มากกว่าหนึ่งล้านองค์ประกอบใน Python และรหัส C # ของคุณ แต่เวลา wallclock สำหรับการทำงานนั้นน้อยกว่าครึ่งหนึ่งของรหัส Python และช้ากว่า C # เพียง 5 เท่า รหัส. นั่นแสดงให้เห็นว่า Rakudo กำลังเรียกใช้รหัส Raku มากกว่าหนึ่งพันเท่าเร็วเท่ากับรหัส Python ที่เทียบเท่ากันและเร็วเป็นร้อยเท่าของรหัส C #
รหัส Raku ดูเหมือนจะมากได้เร็วขึ้นเนื่องจากตารางจะถูกเริ่มต้นได้อย่างเฉื่อยชาxx Inf
โดยใช้ 4งานที่สำคัญเพียงอย่างเดียวเกิดขึ้นกับการเรียกใช้say
บรรทัด สิ่งนี้ทำให้เกิดการสร้างอาร์เรย์มิติแรก 100,000 ชุดจากนั้นจึงเติมอาร์เรย์มิติที่สองที่ 100,000 ด้วยองค์ประกอบ 100,000 เพื่อให้say
สามารถแสดงการ0
จัดเก็บในองค์ประกอบสุดท้ายของอาร์เรย์นั้น
มีมากกว่าหนึ่งวิธีที่จะทำ
ปัญหาหนึ่งที่อยู่ภายใต้คำถามของคุณคือมีมากกว่าหนึ่งวิธีที่จะทำ 5หากคุณพบกับประสิทธิภาพที่ไม่ดีสำหรับโค้ดที่ความเร็วมีความสำคัญการเขียนโค้ดต่างกันอย่างที่ฉันได้ทำอาจสร้างความแตกต่างได้อย่างมาก 6
(อีกตัวเลือกที่ดีจริงๆคือถามคำถาม SO ... )
อนาคต
Raku ได้รับการออกแบบอย่างระมัดระวังเพื่อจะสูงการเพิ่มประสิทธิภาพสามารถคือสามารถที่จะวันหนึ่งวิ่งให้เร็วขึ้นมากการทำงานของคอมไพเลอร์ที่เพียงพอในช่วงปีที่ผ่านมากว่าการพูด, Perl 5 หรืองูหลาม 3 สามารถในทางทฤษฎีเรียกเคยจนกว่าพวกเขาจะไปผ่านภาคพื้นดิน ออกแบบและคอมไพเลอร์ที่สอดคล้องกันเป็นเวลาหลายปี
การเปรียบเทียบที่ค่อนข้างโอเคคือสิ่งที่เกิดขึ้นกับประสิทธิภาพของ Java ในช่วง 25 ปีที่ผ่านมา Rakudo / NQP / MoarVM ประมาณครึ่งทางผ่านกระบวนการสุกที่สแต็ก Java ผ่านไปแล้ว
เชิงอรรถ
1ฉันสามารถเขียนmy $table := ...
ได้ แต่การประกาศในแบบฟอร์มmy \foo ...
กำจัดการพิจารณาของ sigils และอนุญาตให้ใช้=
มากกว่า:=
ที่จะต้องใช้กับตัวบ่งชี้ sigil'd (ในฐานะโบนัสการ "ตัดออก sigil" ให้ผลลัพธ์เป็นตัวบ่งชี้ที่ปราศจาก sigil คุ้นเคยกับ coders ในหลายภาษาที่ไม่ได้ใช้ sigils ซึ่งแน่นอนรวมถึง Python และ C #)
2 การปรับรูปแบบในวันหนึ่งอาจส่งผลให้การดำเนินการของอาเรย์เร็วขึ้นสำหรับบางโค้ด ในระหว่างนี้ดังที่ได้กล่าวไว้ในความคิดเห็นเกี่ยวกับคำถามของคุณขณะนี้มันตรงกันข้ามอย่างชัดเจนทำให้ช้าลงอย่างมีนัยสำคัญ ฉันคิดว่าส่วนใหญ่เพราะทุกการเข้าถึงอาร์เรย์จะถูกอย่างไร้เดียงสาแบบไดนามิกขอบเขตการตรวจสอบในขณะนี้ทุกอย่างช้าลงและยังได้รับความพยายามที่จะใช้ขนาดคงที่ไปสู่สิ่งที่ช่วยเพิ่มความเร็วในไม่มี นอกจากนี้เมื่อฉันพยายามหาวิธีแก้ปัญหาที่รวดเร็วสำหรับโค้ดของคุณฉันไม่สามารถหาอันที่ใช้อาร์เรย์ขนาดคงที่เนื่องจากการดำเนินการหลายอย่างในอาร์เรย์ขนาดคงที่ซึ่งยังไม่มีการใช้งานในปัจจุบัน หวังว่าสิ่งเหล่านี้จะได้รับการดำเนินการในหนึ่งวัน แต่คาดว่าจะไม่เป็นจุดเจ็บปวดที่เพียงพอสำหรับทุกคนในการดำเนินการให้เป็นปัจจุบัน
3ในขณะที่เขียนสิ่งนี้TIOใช้ Python 3.7.4 ตั้งแต่เดือนมิถุนายน 2019 และ Rakudo v2018.12 ตั้งแต่เดือนธันวาคม 2561 ในขณะนี้ประสิทธิภาพของ Rakudo กำลังพัฒนาขึ้นอย่างรวดเร็วกว่าล่าม Python 3 อย่างเป็นทางการดังนั้นฉันจะ คาดว่าช่องว่างระหว่าง Rakudo ล่าสุดและ Python ล่าสุดเมื่อ Rakudo ช้าลงจะแคบลงกว่าที่ระบุไว้ในคำตอบนี้ โดยเฉพาะอย่างยิ่งงานปัจจุบันมีการปรับปรุงประสิทธิภาพของการมอบหมายอย่างมีนัยสำคัญ
4 xx
ค่าเริ่มต้นสำหรับการประมวลผลที่ขี้เกียจ แต่นิพจน์บางอย่างบังคับให้มีการประเมินผลที่กระตือรือร้นเนื่องจากความหมายของภาษาหรือข้อ จำกัด ของคอมไพเลอร์ในปัจจุบัน ใน v2018.12 Rakudo ปีเก่าสำหรับการแสดงออกของรูปแบบที่[ [ foo xx bar ] xx baz ]
จะยังคงขี้เกียจและไม่ได้ถูกบังคับให้ประเมินกระหายทั้งสอง bar
และจะต้องเป็นbaz
Inf
ในทางตรงกันข้ามคือขี้เกียจที่มีการใช้ไม่มีmy \table = [0 xx 100_000 for ^100_000]
Inf
(รหัสหลังคือการจัดเก็บ 100,000 Seq
s ในมิติแรกมากกว่า 100,000 Array
s - say WHAT table[0]
แสดงSeq
มากกว่าArray
- แต่รหัสส่วนใหญ่จะไม่สามารถเห็นความแตกต่าง - say table[99_999;99_999]
จะยังคงแสดง0
)
5ชาวบ้านบางคนคิดว่ามันเป็นจุดอ่อนที่จะยอมรับว่ามีมากกว่าหนึ่งวิธีในการคิดและการแก้ปัญหาของการแก้ปัญหา ในความเป็นจริงมันมีความแข็งแกร่งอย่างน้อยสามประการ ประการแรกโดยทั่วไปปัญหาที่ไม่ได้รับใด ๆ สามารถแก้ไขได้ด้วยอัลกอริทึมที่แตกต่างกันจำนวนมากที่มีความแตกต่างอย่างมากในโปรไฟล์ประสิทธิภาพ คำตอบนี้รวมถึงวิธีการที่มีอยู่แล้วใน Rakudo ซึ่งมีอายุหนึ่งปีซึ่งจะเร็วกว่าการใช้ Python มากกว่าพันเท่าในบางสถานการณ์ ประการที่สองภาษาที่มีความยืดหยุ่นและมีกระบวนทัศน์ที่หลากหลายเช่น Raku อนุญาตให้ coder (หรือทีมงานของผู้เขียนโค้ด) แสดงวิธีแก้ปัญหาที่พวกเขาคิดว่าสง่างามและบำรุงรักษาหรือที่เพิ่งทำงานเสร็จตามสิ่งที่พวกเขาทำคิดว่าดีที่สุดไม่ใช่สิ่งที่ภาษากำหนด ประการที่สามประสิทธิภาพของ Rakudo ในฐานะที่เป็นคอมไพเลอร์ที่ปรับให้เหมาะสมที่สุดคือตัวแปรที่สะดุดตาในปัจจุบัน โชคดีที่มันมี profiler 6ที่ยอดเยี่ยมดังนั้นใคร ๆ ก็สามารถเห็นได้ว่าคอขวดอยู่ตรงไหนและมีความยืดหยุ่นที่ดีเยี่ยมดังนั้นเราสามารถลองเข้ารหัสแบบอื่นได้
6เมื่อเรื่องประสิทธิภาพการทำงานหรือถ้าคุณกำลังตรวจสอบปัญหาการปฏิบัติงานให้คำปรึกษาหน้า doc Raku ต่อประสิทธิภาพการทำงาน ; หน้านี้ครอบคลุมตัวเลือกมากมายรวมถึงการใช้งาน Rakudo Profiler
@grid[4000;4000]
) รหัสหลามไม่ได้ใช้อาร์เรย์ที่มีรูปร่างและคุณลองแบบเดียวกันใน Raku คุณจะได้เวลาที่ดีกว่า:my @grid = [[0 xx 4000] xx 4000];
มันหมายความว่าคุณต้องเข้าถึงด้วยไม่@grid[0][0]
@grid[0;0]
ฉันคิดว่านี่เป็นส่วนใหญ่เพราะอาร์เรย์ที่มีรูปร่างยังคงทำงานอยู่