เป็นปัญหาหรือไม่ที่จะเป็นโปรแกรมเมอร์ที่ไม่มีความรู้เกี่ยวกับความซับซ้อนในการคำนวณ


30

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

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


3
ประกาศผู้ดูแล : กรุณาอย่าใช้ความคิดเห็นสำหรับการอภิปรายเพิ่มเติมหรือเพื่อโพสต์คำตอบที่มีสาระสำคัญ คุณสามารถใช้ห้องแชทเพื่อหารือเกี่ยวกับคำถามนี้ ความคิดเห็นก่อนหน้านี้ถูกย้ายไปที่นั่น
Gilles 'หยุดความชั่วร้าย'

4
ชื่อของคุณคือโปรแกรมเมอร์ แต่คำถามของคุณคือนักเรียน โดยทั่วไป 'โปรแกรมเมอร์' หมายถึง 'โปรแกรมเมอร์มืออาชีพ' - คุณถามว่ามันเป็นปัญหาหรือไม่หากเป็นโปรแกรมเมอร์มืออาชีพที่ไม่มีความรู้เรื่องความซับซ้อนในการคำนวณ? หรือไม่ว่าจะเป็นการดีถ้านักเรียนเขียนโปรแกรมไม่มีความรู้นั้น ทั้งสองเป็นคำถามที่แตกต่างกันแม้ว่ามันจะกลายเป็นว่าพวกเขามีคำตอบเดียวกัน
corsiKa

คำตอบ:


42

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

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

ข้อผิดพลาดทั่วไปที่นักเรียนทำในหลักสูตรอัลกอริทึมของเราคือการทำซ้ำในอาร์เรย์ดังนี้:

while array not empty
    examine first element of array
    remove first element from array

นี่อาจไม่ใช่รหัสที่สวยที่สุด แต่ในโปรแกรมที่ซับซ้อนบางอย่างเช่นนี้อาจปรากฏขึ้นโดยที่โปรแกรมเมอร์ไม่ได้รับรู้ ตอนนี้ปัญหาของโปรแกรมนี้คืออะไร?

สมมติว่าเราทำงานบนชุดข้อมูลที่องค์ประกอบ เมื่อเปรียบเทียบกับโปรแกรมต่อไปนี้โปรแกรมเดิมจะทำงานช้าลง100.00050.000

while array not empty
    examine last element of array
    remove last element from array

ฉันหวังว่าคุณจะเห็นด้วยว่าการมีความรู้ในการทำให้โปรแกรมของคุณทำงานได้เร็วขึ้นครั้งน่าจะเป็นสิ่งสำคัญสำหรับโปรแกรมเมอร์ การทำความเข้าใจความแตกต่างระหว่างโปรแกรมทั้งสองนั้นต้องการความรู้พื้นฐานเกี่ยวกับทฤษฎีความซับซ้อนและความรู้เกี่ยวกับรายละเอียดของภาษาที่คุณกำลังเขียนโปรแกรม50.000

ในภาษาเทียมของฉัน "การลบองค์ประกอบออกจากอาร์เรย์" เลื่อนองค์ประกอบทั้งหมดไปทางขวาขององค์ประกอบที่ถูกลบหนึ่งตำแหน่งจากด้านซ้าย สิ่งนี้ทำให้การลบองค์ประกอบสุดท้ายเป็นการดำเนินการเนื่องจากเพื่อที่เราจะต้องโต้ตอบกับ 1 องค์ประกอบเท่านั้น การลบองค์ประกอบแรกคือเนื่องจากเพื่อที่จะลบองค์ประกอบแรกเราจำเป็นต้องเปลี่ยนองค์ประกอบอื่น ๆ ทั้งหมดหนึ่งตำแหน่งไปทางซ้ายเช่นกันO(1)O(n)n1

แบบฝึกหัดพื้นฐานที่ซับซ้อนมากคือการพิสูจน์ว่าโปรแกรมแรกจะดำเนินการในขณะที่โปรแกรมที่สองใช้การดำเนินงานเท่านั้น หากคุณเสียบคุณจะเห็นว่าโปรแกรมหนึ่งมีประสิทธิภาพมากกว่าโปรแกรมอื่นอย่างเห็นได้ชัด12n2nn=100.000

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

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


10
"So long as you are not dealing with huge data sets you will be fine not knowing complexity"สิ่งนี้มักเป็นจริง แต่ไม่เสมอไป ตัวอย่างเช่นO(n!)อัลกอริทึมจะไม่สามารถทำงานได้แม้จะมีชุดข้อมูลที่ค่อนข้างเล็ก ถ้าคุณใช้O(n!)ขั้นตอนวิธีการที่คุณจะได้ใช้O(n^2)โปรแกรมของคุณจะใช้เวลา 36,288 ครั้งนานในการดำเนินการเกี่ยวกับขนาดของข้อมูลของ10 ขนาดข้อมูล 20 คุณกำลังดู 2.4 การดำเนินงานล้านล้าน
reirab

1
ฉันคิดว่าตัวอย่างของ @ reirab ควรรวมอยู่ในคำตอบ มันน่าทึ่งและพิสูจน์จุดของคุณอย่างเด็ดขาดมากขึ้น และฉันถูกกัดด้วยอัลกอริธึมส่วนตัวก่อนที่ฉันจะเรียนรู้ความซับซ้อนของการคำนวณ
Siyuan Ren

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

"การเข้าใจความแตกต่างระหว่างโปรแกรมทั้งสองนั้นต้องการความรู้พื้นฐานเกี่ยวกับทฤษฎีความซับซ้อน" - ฉันคิดว่านี่เป็นตัวอย่างที่พิเศษไม่ได้ คุณสามารถโพรไฟล์มันสังเกตว่าตลอดเวลาใน "ลบองค์ประกอบ" รู้ (โดยไม่เข้าใจทฤษฎีความซับซ้อน) ว่าการลบองค์ประกอบสุดท้ายเร็วกว่าการเอาองค์ประกอบแรกทำการเปลี่ยนแปลงและทำให้โปรแกรมเร็วขึ้น ข้อดีของการทำความเข้าใจทฤษฎีความซับซ้อนก็คือมันช่วยให้คุณมีปริมาณของปัญหาดังกล่าวโดยไม่ต้องทำโปรไฟล์ดังนั้นคุณสามารถเพิ่มประสิทธิภาพ "ก่อนกำหนด" ได้
Steve Jessop

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

26

นี่เป็นข้อโต้แย้งของคำตอบของTom van der Zandenซึ่งระบุว่านี่เป็นสิ่งที่ต้องทำ

สิ่งที่เป็นส่วนใหญ่ช้ากว่า 50,000 ครั้งไม่เกี่ยวข้อง (เว้นแต่คุณจะทำงานที่ Google แน่นอน)

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

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

ฉันเป็นโปรแกรมเมอร์มืออาชีพมานานกว่าห้าปีแล้วและฉันไม่เคยคิดว่าจะต้องคิดเกี่ยวกับความซับซ้อนของการคำนวณเมื่อวนลูปในลูป O (M * N) เพราะการดำเนินการจะเร็วหรือ M และ N เป็นเช่นนั้นเสมอ เล็ก

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

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


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

2
@Kevin Krumwiede ฉันเห็นด้วยกับคุณอย่างเต็มที่ว่าการเพิ่มประสิทธิภาพการเรียงลำดับสำหรับชุดข้อมูลที่ไม่สำคัญนั้นเกินความจำเป็น แต่มันยังแสดงให้เห็นว่าอย่างน้อยการมีความเข้าใจความซับซ้อนยังคงเป็นสิ่งสำคัญ ความเข้าใจคือสิ่งที่จะนำคุณไปสู่การตัดสินใจว่าการเรียงลำดับฟองนั้นเหมาะสมเมื่อเทียบกับขั้นตอนวิธีที่ซับซ้อนกว่า
Kent A.

4
เมื่อคุณรู้ว่าชุดข้อมูลนั้นมีขนาดเล็กในทุกกรณีคุณสามารถหลีกเลี่ยงสิ่งเหล่านี้ได้ คุณต้องระวังความซับซ้อนที่มากเกินไปในสิ่งที่เรียกว่าภายในลูป - ไม่นานมานี้ฉันได้ตัดรันไทม์หนึ่งนาทีเป็นวินาทีนี้ ฉันยังพบปัญหา O (n ^ 8) หนึ่งครั้ง (การตรวจสอบความถูกต้องของข้อมูล) การดูแลจำนวนมากทำให้ลดลงถึง 12 ชั่วโมง
Loren Pechtel

7
ฉันไม่เคยพบว่าจำเป็นต้องคิดเกี่ยวกับความซับซ้อนของการคำนวณเมื่อวนลูปภายในลูป O (M * N) เพราะการดำเนินการจะเร็วมากหรือ M และ N นั้นเล็กเสมอ - แดกดันข้อโต้แย้งที่คุณให้แสดงให้เห็นว่าคุณคิดเกี่ยวกับความซับซ้อนในการคำนวณ คุณตัดสินใจว่าไม่ใช่ปัญหาที่เกี่ยวข้องกับสิ่งที่คุณกำลังทำและอาจถูกต้อง แต่คุณยังคงตระหนักถึงการมีอยู่ของปัญหานี้และถ้ามันจะก่อให้เกิดปัญหาคุณสามารถตอบสนองก่อนที่จะเกิดผลกระทบร้ายแรง ระดับผู้ใช้
Wrzlprmft

4
การเพิ่มประสิทธิภาพก่อนวัยอันควรเป็นรากของความชั่วร้ายทั้งหมด แต่การมองโลกในแง่ร้ายก่อนวัยอันควรเป็นรากของผู้ใช้ที่รำคาญใจอย่างน้อย คุณอาจไม่จำเป็นต้องสามารถแก้ไขความสัมพันธ์ที่เกิดซ้ำได้ แต่อย่างน้อยที่สุดคุณไม่สามารถบอกความแตกต่างระหว่าง O (1), O (N) และ O (N ^ 2) โดยเฉพาะอย่างยิ่งเมื่อคุณ รังของลูปบางคนจะต้องทำความสะอาดความยุ่งเหยิงในภายหลัง ที่มา: ความยุ่งเหยิงที่ฉันต้องทำความสะอาดในภายหลัง ปัจจัย 50.000 นั้นใหญ่มากจนคุณรู้ดีว่าคุณยังสามารถซื้อได้ในภายหลังเมื่อปัจจัยการผลิตของคุณเติบโตขึ้น
Jeroen Mostert

14

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

ไม่ว่าจะพูดอะไรฉันก็สอนตัวเองอยู่ ฉันไม่เคยพบสัญกรณ์ O จนกระทั่งฉันเริ่มสัมภาษณ์เมื่อไม่กี่ปีที่ผ่านมา มันไม่เคยเกิดขึ้นในการทำงานอย่างมืออาชีพของฉันยกเว้นระหว่างการสัมภาษณ์ ดังนั้นฉันต้องเรียนรู้พื้นฐานเพื่อจัดการกับคำถามนั้นในการสัมภาษณ์

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

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

ขอให้โชคดีกับคุณ!


2
ดังนั้นคำตอบของคุณคือ "ใช่"?
กราฟิลส์

6
TL; DR: "ใช่" อย่างไรก็ตามจากประสบการณ์ของฉันคุณจะไม่พูดถึงความซับซ้อนของการคำนวณในงานส่วนใหญ่หลังจากที่คุณได้รับการว่าจ้าง ใช่ทราบโครงสร้างข้อมูลและประสิทธิภาพการทำงานของพวกเขา แต่เพียงแค่รู้ว่าอัลกอริทึมคือ O (n) หรืออะไรก็ตามที่โปรแกรมเมอร์ทำไม่ได้ มันจะดีกว่ามากที่จะมุ่งเน้นไปที่การเขียนโค้ดที่ดีอย่างรวดเร็วและจากนั้นปรับจุดร้อนให้เหมาะสมในภายหลัง ความสามารถในการอ่านและการบำรุงรักษามักจะมีความสำคัญต่อโค้ดส่วนใหญ่มากกว่าประสิทธิภาพ
Scott Schafer

3
ฉันคิดว่าอาจเกิดขึ้นว่าความซับซ้อนเกิดขึ้นในองค์กร แต่ข้อกังวลแรกที่แท้จริงสำหรับ บริษัท คือการจัดส่ง : ถ้าใช้งานได้ดีพอจนกว่าจะมีงบประมาณเพียงพอในการปรับปรุงแอพหรือลูกค้ากลับมาบ่นเรื่องคนจน การแสดง ในสถานการณ์ b2b สำหรับโครงการ adhoc อาจเป็นเรื่องแปลก ใน b2c หรือในตลาดที่มีการแข่งขันสูง (นอกผลิตภัณฑ์ชั้นวาง) มันอาจจะเกิดขึ้นบ่อยครั้งขึ้นโดยมีผลโดยตรงจากการเพิ่มแถบรายการสำหรับการจ้างงานใหม่
didierc

4
@didierc "Good พอ" ก็เป็นสิ่งที่แบ่งสิ่งตลอดเวลา
กราฟิลส์

1
@didierc 1) คนที่มีภูมิหลังที่มั่นคงใน CS ทำ (หวังว่า) มีสัญชาตญาณที่ดีสำหรับสิ่งที่ถูกต้องและสิ่งที่ไม่ในขณะที่นักแก้ปัญหาเฉพาะกิจอาจกระทำผิด "ง่าย" ตรวจสอบให้แน่ใจว่าการดำเนินการหลังจากการรวบรวมทวีคูณเป็นสิ่งที่เฉพาะเจาะจงเป็นอย่างมากไม่น่ารำคาญและเป็นปัญหาที่ไม่ได้แก้ไข 2) ไม่มี
กราฟิลส์

9

คำถามคืออัตนัยมากดังนั้นผมคิดว่าคำตอบคือมันขึ้นอยู่กับ

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

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

ในระยะสั้นฉันคิดว่าการเข้าใจความซับซ้อนชัดเจนทำให้คุณเป็นโปรแกรมเมอร์ที่ดีขึ้น


1
ฉันคิดว่าคุณมีความคิดที่ถูกต้อง แต่ "ส่วนตัว" ไม่ได้อธิบายปัญหานี้อย่างเพียงพอ "สถานการณ์" จะเป็นคำที่ดีกว่า นอกจากนี้หนึ่งสามารถเขียนโปรแกรมช้ามากที่ไม่ทำงานกับข้อมูลจำนวนมาก ฉันเพิ่งตอบคำถามเกี่ยวกับ math.se เกี่ยวกับการเป็นตัวแทน / การจัดเก็บพหุนาม ซึ่งมักจะเกี่ยวข้องกับข้อมูลจำนวนเล็กน้อยเช่น ~ ชื่อพหุนาม 1,000 คำนั้นเป็นเรื่องปกติ แต่มีความแตกต่างในโลกแห่งความเป็นจริงอย่างมากในประสิทธิภาพ (หลายร้อยหรือหลายพันวินาทีเมื่อเทียบกับไม่กี่วินาทีสำหรับการคูณ) ขึ้นอยู่กับการใช้งาน
Fizz

4

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

มันเป็นปัญหาน้อยสำหรับผู้ใช้อัลกอริทึมสมมติว่าอัลกอริทึมที่มีให้นั้นมีคุณภาพดี สิ่งนี้เป็นจริงสำหรับนักพัฒนาที่ใช้ภาษาที่มีไลบรารี่มาตรฐานที่สำคัญและระบุไว้อย่างดีพวกเขาเพียงแค่ต้องรู้วิธีเลือกอัลกอริทึมที่ตรงกับความต้องการ ปัญหาเกิดขึ้นเมื่อมีอัลกอริธึมหลายอย่างในประเภท (พูด, การเรียงลำดับ) ที่มีอยู่ในห้องสมุดเพราะความซับซ้อนมักเป็นหนึ่งในเกณฑ์ในการเลือกระหว่าง นักพัฒนาที่ไม่เข้าใจความซับซ้อนนั้นไม่สามารถเข้าใจพื้นฐานในการเลือกอัลกอริทึมที่มีประสิทธิภาพสำหรับงานของพวกเขาในมือ

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


3

ขึ้นอยู่กับ แต่ไม่ได้ขึ้นอยู่กับปริมาณข้อมูลที่คุณทำงานด้วย แต่ขึ้นอยู่กับประเภทของงานที่คุณทำโปรแกรมที่คุณพัฒนา

ลองเรียกโปรแกรมเมอร์ที่ไม่รู้เกี่ยวกับความซับซ้อนของโปรแกรม noobish

โปรแกรมเมอร์ noobish สามารถทำได้:

  • พัฒนาฐานข้อมูลขนาดใหญ่ - เขาไม่จำเป็นต้องรู้ว่ามันทำงานอย่างไรภายในทั้งหมดที่เขาต้องรู้คือกฎเกี่ยวกับการพัฒนาฐานข้อมูล เขารู้สิ่งต่าง ๆ เช่น: สิ่งที่ควรได้รับการจัดทำดัชนี ... ซึ่งจะเป็นการดีกว่าที่จะทำข้อมูลซ้ำซ้อนซึ่งไม่ได้ ...
  • ทำเกม - เขาต้องศึกษาว่าเอ็นจิ้นเกมทำงานอย่างไรและทำตามกระบวนทัศน์เกมและคอมพิวเตอร์กราฟิกเป็นปัญหาใหญ่ของข้อมูล พิจารณา 1920 * 1080 * 32bit = cca 7.9MB สำหรับรูปภาพ / เฟรมเดียว ... @ 60 FPS อย่างน้อย 475MB / s พิจารณาว่าเพียงหนึ่งสำเนาที่ไม่จำเป็นของรูปภาพแบบเต็มหน้าจอจะทำให้ปริมาณงานหน่วยความจำประมาณ 500MB ต่อวินาที แต่เขาไม่จำเป็นต้องสนใจสิ่งนั้นเพราะเขาใช้แค่เครื่องยนต์!

โปรแกรมเมอร์ noobish ไม่ควรทำ:

  • พัฒนาโปรแกรมที่ซับซ้อนที่ใช้บ่อยมากไม่ว่าขนาดของข้อมูลจะทำงานด้วย ... ตัวอย่างเช่นข้อมูลขนาดเล็กจะไม่ทำให้เกิดผลกระทบที่เห็นได้ชัดเจนของการแก้ปัญหาที่ไม่เหมาะสมในระหว่างการพัฒนาเพราะมันจะช้ากว่าเวลารวบรวม ฯลฯ ดังนั้น 0.5 วินาทีสำหรับโปรแกรมง่ายๆที่ไม่มากนักจากมุมมองของโปรแกรมเมอร์ noobish ลองพิจารณาเซิร์ฟเวอร์เซิร์ฟเวอร์ที่รันโปรแกรมนี้ยี่สิบครั้งต่อวินาที มันจะต้องมี 10 คะแนนเพื่อให้สามารถรักษาโหลดนั้น!
  • พัฒนาโปรแกรมสำหรับอุปกรณ์ฝังตัว อุปกรณ์ฝังตัวทำงานกับข้อมูลขนาดเล็ก แต่จำเป็นต้องมีประสิทธิภาพเท่าที่จะเป็นไปได้เนื่องจากการดำเนินการซ้ำซ้อนทำให้เกิดการใช้พลังงานที่ไม่จำเป็น

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

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


1
คำตอบนี้อาจปรับปรุงได้หากใช้ป้ายกำกับที่เป็นกลางมากกว่าหรือไม่มีป้ายกำกับเลยเหมือนกับคำตอบอื่น ๆ ที่ใช้คำว่า "โปรแกรมเมอร์ไร้ความสามารถ"
Moby Disk

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

3

ฉันค่อนข้างลังเลที่จะเขียนคำตอบที่นี่ แต่เนื่องจากฉันพบว่าตัวเองมี nitpicking ในหลาย ๆ คน '[ความคิดเห็นบางส่วนของฉันถูกย้ายไปแชท] นี่คือวิธีที่ฉันเห็น ...

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

ระดับของความรู้และทักษะ / ความสามารถที่จำเป็นในเรื่องดังกล่าวนั้นขึ้นอยู่กับสิ่งที่เราทำ การจัดเรียงO ( ) ที่ไร้เดียงสาสมบูรณ์บางครั้งกล่าวกันว่าเป็นสาเหตุหลักของโปรแกรมที่ช้า[อ้างจำเป็น]แต่กระดาษ SIGCSE ในปี 2003ระบุว่า "การเรียงลำดับการแทรกถูกใช้เพื่อจัดเรียงอาร์เรย์ย่อย (ย่อย) ในไลบรารีมาตรฐาน " ในทางกลับกันการเพิ่มประสิทธิภาพก่อนวัยอันควรมาจากคนที่ไม่เข้าใจว่าหมายถึงasymptotic (ความซับซ้อนของการคำนวณเป็นตัวชี้วัด) บางครั้งเป็นปัญหาในการฝึกเขียนโปรแกรม อย่างไรก็ตามประเด็นของการรู้อย่างน้อยเมื่อความซับซ้อนของการคำนวณมีความสำคัญคือสาเหตุที่คุณต้องมีเงื่อนงำเกี่ยวกับเรื่องนี้อย่างน้อยก็ในระดับปริญญาตรีn2

ฉันจะกล้าเปรียบเทียบสถานการณ์ของการรู้ว่าเมื่อไหร่ที่จะใช้แนวคิดความซับซ้อนในการคำนวณ (และรู้ว่าเมื่อใดที่คุณสามารถเพิกเฉยได้อย่างปลอดภัย) กับการปฏิบัติทั่วไป (นอกโลก Java) ในการใช้โค้ดประสิทธิภาพที่มีความละเอียดอ่อนใน C สิ่งต่างๆใน Python และอื่น ๆ (เช่นกันสิ่งนี้ถูกเรียกใน Julia พูดถึง"การประนีประนอมมาตรฐาน" ) การรู้ว่าเมื่อใดที่คุณไม่ต้องคิดเกี่ยวกับประสิทธิภาพช่วยให้คุณประหยัดเวลาในการเขียนโปรแกรมซึ่งเป็นสินค้าที่มีคุณค่า

และอีกประเด็นหนึ่งคือการรู้ว่าความซับซ้อนในการคำนวณจะไม่ทำให้คุณเก่งในการเพิ่มประสิทธิภาพโปรแกรมโดยอัตโนมัติ คุณต้องเข้าใจสิ่งที่เกี่ยวข้องกับสถาปัตยกรรมมากขึ้นเช่นที่ตั้งแคช, บางครั้งไพพ์ไลน์, และในปัจจุบันการเขียนโปรแกรมแบบขนาน / มัลติคอร์เช่นกัน; หลังมีทั้งทฤษฎีความซับซ้อนของตัวเองและการพิจารณาในทางปฏิบัติเช่นกัน รสชาติของกระดาษในช่วงหลังของSOSP ปี 2556 “ ทุกรูปแบบการล็อคมีชื่อเสียงสิบห้านาทีไม่มีรูปแบบการล็อคเก้าแบบที่เราพิจารณาว่ามีประสิทธิภาพเหนือกว่ารูปแบบอื่น ๆ อย่างต่อเนื่องในสถาปัตยกรรมเป้าหมายหรือปริมาณงานทั้งหมดพูดอย่างเคร่งครัด ดังนั้นจึงควรเลือกอัลกอริทึมการล็อคตามแพลตฟอร์มฮาร์ดแวร์และปริมาณงานที่คาดหวัง "


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

1
ในทางปฏิบัติ (โดยไม่ได้ตั้งใจ) Schlemiel อัลกอริธึมของ Painterนั้นบ่อยกว่าการจัดเรียง O (n ^ 2) มาก
Peter Mortensen

-1

หากคุณไม่รู้จัก big-O คุณควรเรียนรู้ มันไม่ยากและมันมีประโยชน์จริงๆ เริ่มต้นด้วยการค้นหาและการเรียงลำดับ

ฉันจะแจ้งให้ทราบว่าจำนวนมากของคำตอบและความคิดเห็นขอแนะนำให้profilingและพวกเขามักจะหมายถึงการใช้เครื่องมือ profiling

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

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

แต่พวกเขาไม่สามารถซ่อนตัวจากเทคนิคนี้


คุณอ้างว่า "บิ๊กโอ้" มีประโยชน์ แต่จากนั้นคุณสนับสนุนแนวทางที่แตกต่าง นอกจากนี้ฉันไม่เห็นวิธีการเรียนรู้ "Big-Oh" (คณิตศาสตร์) สามารถ "เริ่มต้นด้วยการค้นหาและการเรียงลำดับ" (ปัญหาอัลกอริทึม)
Raphael

@ ราฟาเอล: ฉันไม่สนับสนุนวิธีการที่แตกต่างกัน - มันเป็น orthogonal.Big-O เป็นความรู้พื้นฐานสำหรับการทำความเข้าใจอัลกอริทึมในขณะที่การค้นหาปัญหาประสิทธิภาพการทำงานในซอฟต์แวร์ที่ไม่ใช่ของเล่นเป็นสิ่งที่คุณทำหลังจากรหัสถูกเขียนและเรียกใช้ (บางครั้งนักวิชาการไม่รู้เรื่องนี้ดังนั้นพวกเขาจึงสอน gprof, ทำอันตรายมากกว่าดี) ในการทำเช่นนั้นคุณอาจจะหรืออาจไม่พบว่าปัญหาคือการใช้อัลกอริทึม O (n * n) ดังนั้นคุณควร สามารถรับรู้ได้ว่า (และ big-O เป็นเพียงคุณสมบัติที่กำหนดทางคณิตศาสตร์ของอัลกอริทึมไม่ใช่วิชาอื่น)
Mike Dunlavey

"และ big-O เป็นเพียงคุณสมบัติที่กำหนดทางคณิตศาสตร์ของอัลกอริทึมไม่ใช่วิชาอื่น" - มันผิดและอันตรายมาก "บิ๊กโอ" กำหนดชั้นของฟังก์ชั่น ; ยังไม่มีอะไรเกี่ยวข้องกับอัลกอริธึมเลย
Raphael

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