Saya ditugaskan latihan di universitas saya. Saya membawanya pulang dan mencoba memprogram algoritma untuk menyelesaikannya, itu adalah sesuatu yang berhubungan dengan grafik, menemukan komponen yang terhubung, saya kira.
Kemudian saya membuat hal paling sepele yang muncul di benak saya dan kemudian ditunjukkan kepada dosen saya. Setelah pengamatan singkat, ia merasa bahwa kompleksitas runtime dari solusi saya tidak dapat diganggu gugat dan menunjukkan sesuatu yang lebih efisien. Dan ada tradisi programmer yang tidak tahu apa itu kompleksitas komputasi (saya salah satunya), jadi apakah itu masalah jika programmer tidak tahu apa itu kompleksitas komputasi?
algorithms
algorithm-analysis
education
applied-theory
Billy Rubina
sumber
sumber
Jawaban:
Ya, saya akan mengatakan mengetahui sesuatu tentang kompleksitas komputasi adalah suatu keharusan bagi setiap programmer yang serius. Selama Anda tidak berurusan dengan kumpulan data besar, Anda akan baik-baik saja tanpa mengetahui kompleksitas, tetapi jika Anda ingin menulis sebuah program yang menangani masalah serius, Anda memerlukannya.
Dalam kasus khusus Anda, contoh Anda menemukan komponen yang terhubung mungkin telah bekerja untuk grafik hingga mengatakan node. Namun, jika Anda mencoba grafik dengan 100.000100 100.000 node maka algoritma dosen Anda mungkin akan mengaturnya dalam 1 detik, sedangkan algoritma Anda akan (tergantung pada seberapa buruk kompleksitasnya) diambil 1 jam, 1 hari, atau mungkin bahkan 1 keabadian.
Kesalahan yang agak umum dilakukan oleh siswa dalam kursus algoritme kami adalah beralih ke array seperti ini:
Ini mungkin bukan kode yang paling indah tetapi dalam program yang rumit sesuatu seperti ini mungkin muncul tanpa disadari oleh programmer. Sekarang, apa masalahnya dengan program ini?
Misalkan kita menjalankannya pada kumpulan data elemen. Dibandingkan dengan program berikut, program sebelumnya akan berjalan 50.000 lebih lambat.100.000 50.000
Saya harap Anda setuju bahwa memiliki pengetahuan untuk membuat program Anda berjalan kali lebih cepat mungkin merupakan hal penting bagi seorang programmer. Memahami perbedaan antara kedua program tersebut membutuhkan beberapa pengetahuan dasar tentang teori kompleksitas dan beberapa pengetahuan tentang rincian bahasa tempat Anda pemrograman.50.000
Dalam bahasa kode pseudocode saya, "menghapus elemen dari array" menggeser semua elemen ke kanan elemen yang dihapus satu posisi dari kiri. Ini membuat menghapus elemen terakhir menjadi operasi karena untuk melakukan itu kita hanya perlu berinteraksi dengan 1 elemen. Menghapus elemen pertama adalah O ( n ) karena untuk menghapus elemen pertama kita perlu menggeser semua yang lain n - 1O ( 1 ) O ( n ) n - 1 satu posisi ke kiri juga.
Latihan yang sangat mendasar dalam kompleksitas adalah untuk membuktikan bahwa program pertama akan melakukan operasi sedangkan program kedua hanya menggunakannoperasi. Jika Anda memasukkann=100.000Anda akan melihat satu program secara drastis lebih efisien daripada yang lain.12n2 n n = 100.000
Ini hanya contoh mainan tetapi sudah membutuhkan pemahaman dasar tentang kompleksitas untuk membedakan antara kedua program, dan jika Anda benar-benar mencoba untuk men-debug / mengoptimalkan program yang lebih rumit yang memiliki kesalahan ini, dibutuhkan pemahaman yang lebih besar untuk menemukan di mana bug itu. Karena kesalahan seperti menghapus elemen dari array dengan cara ini dapat disembunyikan dengan sangat baik oleh abstraksi dalam kode.
Memiliki pemahaman yang baik tentang kompleksitas juga membantu ketika membandingkan dua pendekatan untuk menyelesaikan masalah. Misalkan Anda telah datang dengan dua pendekatan berbeda untuk memecahkan masalah komponen yang terhubung pada Anda sendiri: untuk memutuskan di antara mereka akan sangat berguna jika Anda dapat (dengan cepat) memperkirakan kerumitan mereka dan memilih yang lebih baik.
sumber
"So long as you are not dealing with huge data sets you will be fine not knowing complexity"
Ini sering benar, tetapi tidak selalu demikian. Misalnya, suatuO(n!)
algoritma tidak akan dapat digunakan bahkan untuk set data yang relatif kecil. Jika Anda menggunakanO(n!)
algoritma di mana Anda bisa menggunakanO(n^2)
program Anda akan memakan waktu 36.288 kali lebih lama untuk dieksekusi pada ukuran data 10 . Pada ukuran data 20, Anda melihat 2,4 triliun operasi.Ini adalah bantahan dari jawaban Tom van der Zanden , yang menyatakan bahwa ini adalah suatu keharusan.
Masalahnya, 50.000 kali lebih lambat tidak relevan (kecuali Anda bekerja di Google tentu saja).
Jika operasi yang Anda lakukan membutuhkan mikrodetik atau jika N Anda tidak pernah di atas ambang batas tertentu (Sebagian besar pengkodean dilakukan saat ini) itu tidak akan PERNAH menjadi masalah. Dalam kasus tersebut, berpikir tentang kompleksitas komputasi hanya akan membuat Anda membuang waktu (dan kemungkinan besar uang).
Kompleksitas komputasi adalah alat untuk memahami mengapa sesuatu mungkin lambat atau skala buruk, dan bagaimana cara memperbaikinya, tetapi sebagian besar waktu adalah sepenuhnya berlebihan.
Saya telah menjadi programmer profesional selama lebih dari lima tahun sekarang dan saya tidak pernah menemukan kebutuhan untuk berpikir tentang kompleksitas komputasi ketika looping di dalam loop O (M * N) karena selalu operasi sangat cepat atau M dan N begitu kecil.
Ada hal-hal yang jauh lebih penting, umum digunakan, dan lebih sulit untuk dipahami oleh siapa pun yang melakukan pekerjaan pemrograman (threading dan profiling adalah contoh yang baik di bidang kinerja).
Tentu saja, ada beberapa hal yang tidak akan pernah bisa Anda lakukan tanpa memahami kompleksitas komputasi (misalnya: menemukan anagram pada kamus), tetapi sebagian besar waktu Anda tidak membutuhkannya.
sumber
Saya telah mengembangkan perangkat lunak selama sekitar tiga puluh tahun, bekerja sebagai kontraktor dan karyawan, dan saya cukup sukses dalam hal itu. Bahasa pertama saya adalah BASIC, tetapi saya dengan cepat belajar sendiri bahasa mesin untuk mendapatkan kecepatan yang layak dari kotak saya yang kurang bertenaga. Saya telah menghabiskan banyak waktu di profiler selama bertahun-tahun dan telah belajar banyak tentang menghasilkan kode yang dioptimalkan dengan cepat dan efisien memori.
Terlepas dari mengatakan, saya belajar sendiri. Saya tidak pernah menemukan notasi O sampai saya mulai mewawancarai beberapa tahun yang lalu. Tidak pernah muncul dalam pekerjaan profesional saya KECUALI selama wawancara. Jadi saya harus mempelajari dasar-dasarnya hanya untuk menangani pertanyaan itu dalam wawancara.
Saya merasa seperti musisi jazz yang tidak bisa membaca lembaran musik. Saya masih bisa bermain dengan baik. Saya tahu tentang hashtable (huh, saya menemukan hashtable sebelum saya tahu bahwa itu sudah ditemukan) dan struktur data penting lainnya, dan saya bahkan mungkin tahu beberapa trik yang tidak mereka ajarkan di sekolah. Tetapi saya pikir kebenarannya adalah jika Anda ingin sukses dalam profesi ini, Anda harus masuk indie atau mempelajari jawaban atas pertanyaan yang akan mereka tanyakan selama wawancara.
Kebetulan, saya baru-baru ini mewawancarai untuk peran pengembang web ujung depan. Mereka mengajukan pertanyaan kepada saya di mana jawabannya membutuhkan pengetahuan tentang kompleksitas komputasi dan logaritma. Saya berhasil mengingat cukup matematika dari dua puluh tahun yang lalu untuk menjawabnya kurang lebih dengan benar, tetapi itu agak menggelegar. Saya tidak pernah harus menggunakan logaritma dalam pengembangan front end.
Semoga beruntung untukmu!
sumber
Pertanyaannya cukup subyektif, jadi saya pikir jawabannya tergantung .
Tidak masalah jika Anda bekerja dengan sejumlah kecil data. Dalam kasus ini, biasanya baik-baik saja untuk menggunakan apa pun misalnya perpustakaan standar yang ditawarkan bahasa Anda.
Namun, ketika Anda berurusan dengan sejumlah besar data, atau karena alasan lain Anda bersikeras bahwa program Anda cepat, maka Anda harus memahami kompleksitas komputasi. Jika tidak, bagaimana Anda tahu bagaimana masalah harus diselesaikan, atau seberapa cepat bahkan mungkin untuk menyelesaikannya? Tetapi memahami teori saja tidak cukup untuk menjadi programmer yang benar-benar baik. Untuk menghasilkan kode yang sangat cepat, saya percaya, Anda juga harus memahami bagaimana misalnya mesin Anda bekerja (cache, tata letak memori, set instruksi), dan apa yang dilakukan kompiler Anda (kompiler melakukan yang terbaik, tetapi tidak sempurna).
Singkatnya, saya pikir memahami kompleksitas dengan jelas membuat Anda seorang programmer yang lebih baik.
sumber
Ini tentu menjadi masalah jika seseorang yang mengembangkan algoritma signifikan tidak memahami kompleksitas algoritma. Pengguna suatu algoritma umumnya mengandalkan kualitas implementasi yang baik yang memiliki karakteristik kinerja yang baik. Meskipun kompleksitas bukan satu-satunya penyumbang karakteristik kinerja suatu algoritma, itu adalah kompleksitas yang signifikan. Seseorang yang tidak memahami kompleksitas algoritma cenderung mengembangkan algoritma dengan karakteristik kinerja yang bermanfaat.
Ini kurang masalah bagi pengguna suatu algoritma, dengan asumsi algoritma yang tersedia berkualitas baik. Ini berlaku untuk pengembang yang menggunakan bahasa yang memiliki pustaka standar yang signifikan, ditentukan dengan baik, standar - mereka hanya perlu tahu cara memilih algoritma yang memenuhi kebutuhan di sana. Masalahnya adalah di mana mereka adalah beberapa algoritma dari beberapa jenis (katakanlah, penyortiran) tersedia dalam perpustakaan, karena kompleksitas sering menjadi salah satu kriteria untuk memilih di antaranya. Pengembang yang tidak memahami kompleksitas kemudian tidak dapat memahami dasar untuk memilih algoritma yang efektif untuk tugas mereka.
Lalu ada pengembang yang fokus pada (karena ingin deskripsi yang lebih baik) masalah non-algoritmik. Misalnya, mereka dapat fokus pada pengembangan antarmuka pengguna yang intuitif. Pengembang seperti itu sering tidak perlu khawatir tentang kompleksitas algoritma meskipun, sekali lagi, mereka mungkin bergantung pada perpustakaan atau kode lain yang sedang dikembangkan dengan kualitas tinggi.
sumber
Itu tergantung, tetapi bukan pada jumlah data yang Anda kerjakan, tetapi pada jenis pekerjaan yang Anda lakukan, program yang Anda kembangkan.
Mari kita panggil programmer yang tidak tahu tentang kompleksitas konseptual noobish programmer.
Pemrogram noobish dapat melakukan:
Programmer noobish seharusnya tidak melakukan:
Jadi, programmer noobish baik-baik saja, ketika Anda hanya ingin menggunakan teknologi. Jadi, ketika datang ke pengembangan solusi baru, teknologi khusus, dll. Maka lebih baik untuk mempekerjakan programmer tidak noobish.
Namun, jika perusahaan tidak mengembangkan teknologi baru, gunakan saja yang sudah dibuat. Membuang bakat untuk merekrut programmer yang terampil dan berbakat. Hal yang sama berlaku, jika Anda tidak ingin bekerja pada teknologi baru dan Anda baik-baik saja menempatkan ide pelanggan ke dalam desain dan program menggunakan kerangka kerja yang sudah dibuat, maka buang-buang waktu Anda, untuk mempelajari sesuatu yang Anda tidak akan pernah perlu, kecuali jika itu hobi Anda dan Anda suka tantangan logis.
sumber
Saya agak ragu-ragu untuk menulis jawaban di sini, tetapi karena saya mendapati diri saya mengolok-olok beberapa orang lain [beberapa komentar saya tergerak untuk mengobrol], inilah bagaimana saya melihatnya ...
Ada tingkat / derajat pengetahuan untuk banyak hal dalam komputasi (dan dengan istilah ini saya kira kira penyatuan ilmu komputer dengan teknologi informasi). Kompleksitas komputasi tentunya adalah bidang yang luas (Apakah Anda tahu apa OptP itu? Atau apa yang dikatakan teorema Abiteboul-Vianu?) Dan juga mengakui banyak kedalaman: kebanyakan orang dengan gelar CS tidak dapat menghasilkan bukti ahli yang masuk ke dalam penelitian publikasi dalam kompleksitas komputasi.
Sejujurnya saya berani membandingkan situasi mengetahui kapan harus menerapkan konsep kompleksitas komputasi (dan mengetahui kapan Anda dapat dengan aman mengabaikannya) dengan praktik yang agak umum (di luar dunia Jawa) menerapkan beberapa kode yang sensitif terhadap kinerja di C dan tidak sensitif terhadap kinerja hal-hal dengan Python dll. (Di samping itu, ini disebut dalam pembicaraan Julia "standar kompromi" .) Mengetahui kapan Anda tidak harus berpikir tentang kinerja menghemat waktu pemrograman Anda, yang juga merupakan komoditas yang cukup berharga.
Dan satu hal lagi adalah mengetahui kompleksitas komputasi tidak akan secara otomatis membuat Anda pandai mengoptimalkan program; Anda perlu memahami lebih banyak hal yang berhubungan dengan arsitektur seperti cache locality, [terkadang] pipelining, dan saat ini pemrograman paralel / multi-core juga; yang terakhir memiliki teori kompleksitas dan pertimbangan praktisnya sendiri; rasa yang terakhir dari kertas SOSP 2013 "Setiap skema penguncian memiliki ketenaran lima belas menit. Tidak satu pun dari sembilan skema penguncian yang kami anggap secara konsisten mengungguli yang lain, pada semua arsitektur target atau beban kerja. Sebenarnya, untuk mencari optimalitas, sebuah Algoritma kunci dengan demikian harus dipilih berdasarkan pada platform perangkat keras dan beban kerja yang diharapkan. "
sumber
Jika Anda tidak tahu besar-O, Anda harus mempelajarinya. Ini tidak sulit, dan ini sangat berguna. Mulai dengan pencarian dan penyortiran.
Saya memperhatikan bahwa banyak jawaban dan komentar merekomendasikan profil , dan hampir selalu berarti menggunakan alat profil .
Masalahnya adalah, alat profiling ada di seluruh peta dalam hal seberapa efektif mereka untuk menemukan apa yang Anda butuhkan untuk mempercepat. Di sini saya telah membuat daftar dan menjelaskan kesalahpahaman yang diderita oleh para profiler.
Hasilnya adalah bahwa program, jika lebih besar dari latihan akademis, dapat berisi raksasa tidur , yang bahkan profiler otomatis terbaik tidak dapat mengekspos. Posting ini menunjukkan beberapa contoh bagaimana masalah kinerja dapat disembunyikan dari profiler.
Tetapi mereka tidak bisa bersembunyi dari teknik ini.
sumber