Multithreading: Apa gunanya lebih banyak thread daripada core?

142

Saya pikir inti dari komputer multi-core adalah bisa menjalankan banyak utas secara bersamaan. Jika demikian, jika Anda memiliki mesin quad-core, apa gunanya memiliki lebih dari 4 utas yang berjalan sekaligus? Bukankah mereka hanya mencuri waktu (Sumber Daya CPU) dari satu sama lain?

Nick Heiner
sumber
52
kami menikmati jenis pertanyaan ini, mereka mempertanyakan sesuatu yang sangat mendasar, yang diterima begitu saja ... tetap datang ..
Srinivas Reddy Thatiparthy
6
Kapan terakhir kali Anda menjalankan Firefox, MS Word, Winamp, Eclipse dan download manager (lebih dari empat program / proses) secara bersamaan di mesin quad core Anda? Juga, satu aplikasi kadang-kadang mungkin menelurkan lebih dari empat utas - bagaimana dengan itu?
Amarghosh
1
Mencuri belum tentu buruk. Anda mungkin memiliki utas dengan prioritas lebih tinggi untuk tugas-tugas penting yang perlu mencuri waktu.
kichik
1
@Amarghosh Saya kira itu adalah pertanyaannya, mengapa satu aplikasi mungkin ingin menelurkan lebih banyak utas daripada inti jika tampaknya tidak membawa manfaat kinerja apa pun. Dan contoh Anda dengan lebih dari empat program tidak cukup relevan di sini. Seperti yang Anda catat dengan benar, itu adalah proses. Fitur multitasking OS (proses multiplexing) sangat sedikit hubungannya dengan utas dalam satu proses.
Aleksandr Ivannikov

Jawaban:

81

Jawabannya berkisar pada tujuan utas, yaitu paralelisme: untuk menjalankan beberapa jalur eksekusi sekaligus. Dalam sistem 'ideal', Anda akan memiliki satu utas mengeksekusi per inti: tidak ada gangguan. Pada kenyataannya ini tidak terjadi. Bahkan jika Anda memiliki empat inti dan empat utas yang berfungsi, proses dan utas Anda akan terus-menerus dialihkan untuk proses dan utas lainnya. Jika Anda menjalankan OS modern, setiap proses memiliki setidaknya satu utas, dan banyak yang lainnya. Semua proses ini berjalan sekaligus. Anda mungkin memiliki beberapa ratus utas yang berjalan di mesin Anda sekarang. Anda tidak akan pernah mendapatkan situasi di mana utas berjalan tanpa memiliki waktu 'dicuri' darinya. (Yah, Anda mungkin jika itugunakan prioritas utas waktu-nyata. Tapi itu jarang terjadi.) berjalan real-time, jika Anda menggunakan OS waktu-nyata atau, bahkan di Windows, gunakan utas prioritas waktu-nyata. Tapi itu jarang terjadi.)

Dengan itu sebagai latar belakang, jawabannya: Ya, lebih dari empat utas pada mesin empat inti sejati dapat memberi Anda situasi di mana mereka 'mencuri waktu satu sama lain', tetapi hanya jika setiap utas individu membutuhkan CPU 100% . Jika utas tidak berfungsi 100% (karena utas UI mungkin tidak, atau utas melakukan sedikit pekerjaan atau menunggu sesuatu yang lain) maka utas lain yang dijadwalkan sebenarnya adalah situasi yang baik.

Ini sebenarnya lebih rumit dari itu:

  • Bagaimana jika Anda memiliki lima bit pekerjaan yang semuanya harus dilakukan sekaligus? Lebih masuk akal untuk menjalankan semuanya sekaligus, daripada menjalankannya empat dan kemudian menjalankan yang kelima nanti.

  • Jarang ada utas yang benar-benar membutuhkan CPU 100%. Saat menggunakan disk atau I / O jaringan, misalnya, mungkin berpotensi menghabiskan waktu menunggu melakukan apa pun yang tidak berguna. Ini adalah situasi yang sangat umum.

  • Jika Anda memiliki pekerjaan yang perlu dijalankan, salah satu mekanisme umum adalah menggunakan threadpool. Tampaknya masuk akal untuk memiliki jumlah utas yang sama dengan inti, namun .Net threadpool memiliki hingga 250 utas yang tersedia per prosesor . Saya tidak yakin mengapa mereka melakukan ini, tetapi dugaan saya adalah untuk melakukan dengan ukuran tugas yang diberikan untuk dijalankan di utas.

Jadi: mencuri waktu bukanlah hal yang buruk (dan tidak benar-benar pencurian, baik: ini adalah bagaimana sistem seharusnya bekerja.) Tulis program multithreaded Anda berdasarkan jenis pekerjaan yang akan dilakukan utas, yang mungkin bukan CPU -terikat. Cari tahu jumlah utas yang Anda butuhkan berdasarkan profil dan pengukuran. Anda mungkin merasa lebih berguna untuk berpikir dalam hal tugas atau pekerjaan, daripada utas: menulis objek kerja dan memberikannya ke kumpulan yang akan dijalankan. Akhirnya, kecuali program Anda benar-benar kritis terhadap kinerja, jangan terlalu khawatir :)

David
sumber
16
+1 untuk "tetapi hanya jika setiap utas individu membutuhkan 100% CPU". Itu adalah asumsi yang tidak saya sadari.
Nick Heiner
Jawaban yang bagus untuk pertanyaan hebat. Terima kasih!
Edgecase
53

Hanya karena ada utas tidak selalu berarti utas aktif. Banyak aplikasi utas melibatkan beberapa utas yang akan tidur sampai saatnya bagi mereka untuk melakukan sesuatu - misalnya, input pengguna memicu utas untuk bangun, melakukan beberapa pemrosesan, dan kembali tidur.

Intinya, utas adalah tugas individu yang dapat beroperasi secara independen satu sama lain, tanpa perlu mengetahui perkembangan tugas lainnya. Sangat mungkin untuk memiliki lebih dari ini daripada Anda memiliki kemampuan untuk berjalan secara bersamaan; mereka masih berguna untuk kenyamanan bahkan jika mereka kadang harus mengantri di belakang satu sama lain.

Amber
sumber
11
Kata baik. Argumen 'satu utas per CPU' hanya berlaku untuk kode yang terikat CPU. Pemrograman asinkron adalah alasan lain untuk menggunakan utas.
Joshua Davis
26

Intinya adalah bahwa, meskipun tidak mendapatkan speedup nyata ketika jumlah thread melebihi jumlah inti, Anda dapat menggunakan utas untuk mengurai potongan-potongan logika yang seharusnya tidak harus saling bergantung.

Bahkan dalam aplikasi yang cukup kompleks, menggunakan utas tunggal mencoba melakukan segalanya dengan cepat membuat hash dari 'aliran' kode Anda. Utas tunggal menghabiskan sebagian besar waktunya polling ini, memeriksa itu, kondisional memanggil rutin sesuai kebutuhan, dan itu menjadi sulit untuk melihat apa pun kecuali sebuah tumpukan kecil.

Bandingkan ini dengan kasus di mana Anda dapat mendedikasikan utas untuk tugas sehingga, melihat setiap utas, Anda dapat melihat apa yang dilakukan utas itu. Misalnya, satu utas mungkin memblokir menunggu input dari soket, mengurai aliran ke dalam pesan, menyaring pesan, dan ketika pesan yang sah datang, meneruskannya ke beberapa utas pekerja lainnya. Utas pekerja dapat mengerjakan input dari sejumlah sumber lain. Kode untuk masing-masing ini akan menunjukkan alur yang bersih dan terarah, tanpa harus melakukan pemeriksaan eksplisit bahwa tidak ada hal lain yang dapat dilakukan.

Memisahkan pekerjaan dengan cara ini memungkinkan aplikasi Anda bergantung pada sistem operasi untuk menjadwalkan apa yang harus dilakukan selanjutnya dengan cpu, sehingga Anda tidak perlu melakukan pemeriksaan bersyarat eksplisit di mana pun dalam aplikasi Anda tentang apa yang mungkin memblokir dan apa yang siap untuk diproses.

JustJeff
sumber
1
Ini adalah pemikiran yang menarik ... Saya selalu mendengar bahwa multithreading suatu aplikasi adalah tambahan kompleksitas, tetapi apa yang Anda katakan masuk akal.
Nick Heiner
Multithreading suatu aplikasi menambah kompleksitas jika permasalahannya tidak dipisahkan secara memadai. Jika itu dirancang dengan sedikit tumpang tindih masalah (dan dengan demikian berbagi negara) itu adalah penghematan bersih dalam masalah kompleksitas.
HANYA PENDAPATAN SAYA yang benar
Ada beberapa cara untuk membuat struktur aplikasi single-threaded sehingga kontrol-aliran lebih jelas di tingkat Anda menulis program. OTOH, jika Anda dapat menyusun utas Anda sehingga hanya menyampaikan pesan satu sama lain (alih-alih memiliki sumber daya bersama), cukup mudah untuk mengetahui apa yang terjadi dan membuat semuanya berfungsi.
Donal Fellows
1
Akan tetapi, harus menunjukkan bahwa menggunakan utas hanya dapat menyederhanakan berbagai hal hingga titik tertentu. Terlalu sering upaya dilakukan untuk membuat dua utas melakukan pekerjaan yang seharusnya dilakukan oleh satu, di mana kompleksitas muncul kembali dalam sekop. Gejala-gejala ini adalah kebutuhan yang berlebihan untuk komunikasi dan sinkronisasi untuk mengoordinasikan beberapa hasil yang diinginkan.
JustJeff
15

Jika utas sedang menunggu sumber daya (seperti memuat nilai dari RAM ke register, disk I / O, akses jaringan, luncurkan proses baru, permintaan basis data, atau menunggu input pengguna), prosesor dapat bekerja pada berbeda utas, dan kembali ke utas pertama setelah sumber tersedia. Ini mengurangi waktu yang dihabiskan CPU menganggur, karena CPU dapat melakukan jutaan operasi alih-alih duduk diam.

Pertimbangkan utas yang perlu membaca data dari hard drive. Pada tahun 2014, inti prosesor khas beroperasi pada 2,5 GHz dan mungkin dapat menjalankan 4 instruksi per siklus. Dengan waktu siklus 0,4 ns, prosesor dapat menjalankan 10 instruksi per nanosecond. Dengan waktu mencari hard drive mekanis biasa sekitar 10 milidetik, prosesor ini mampu mengeksekusi 100 juta instruksi dalam waktu yang diperlukan untuk membaca nilai dari hard drive. Mungkin ada peningkatan kinerja yang signifikan dengan hard drive dengan cache kecil (4 MB buffer) dan drive hybrid dengan beberapa GB penyimpanan, karena latensi data untuk membaca berurutan atau membaca dari bagian hybrid mungkin beberapa urutan besarnya lebih cepat.

Inti prosesor dapat beralih di antara utas (biaya untuk menjeda dan memulai kembali utas adalah sekitar 100 siklus clock) sementara utas pertama menunggu input latensi tinggi (sesuatu yang lebih mahal daripada register (1 jam) dan RAM (5 nanodetik)) Ini termasuk disk I / O, akses jaringan (latensi 250 ms), membaca data dari CD atau bus lambat, atau panggilan basis data. Memiliki lebih banyak utas daripada inti berarti pekerjaan yang bermanfaat dapat dilakukan sementara tugas dengan latensi tinggi diselesaikan.

CPU memiliki penjadwal ulir yang memberikan prioritas pada setiap utas, dan memungkinkan utas untuk tidur, kemudian melanjutkan setelah waktu yang telah ditentukan. Ini adalah tugas penjadwal utas untuk mengurangi labrakan, yang akan terjadi jika setiap utas mengeksekusi hanya 100 instruksi sebelum dimasukkan kembali ke mode tidur. Overhead switching threads akan mengurangi total throughput berguna inti prosesor.

Untuk alasan ini, Anda mungkin ingin memecah masalah Anda menjadi sejumlah utas. Jika Anda menulis kode untuk melakukan perkalian matriks, membuat satu utas per sel dalam matriks keluaran mungkin berlebihan, sedangkan satu utas per baris atau per n baris dalam matriks keluaran dapat mengurangi biaya overhead untuk membuat, menjeda, dan melanjutkan utas.

Ini juga mengapa prediksi cabang penting. Jika Anda memiliki pernyataan if yang mengharuskan memuat nilai dari RAM tetapi isi pernyataan if dan else menggunakan nilai yang sudah dimuat ke register, prosesor dapat menjalankan satu atau kedua cabang sebelum kondisi dievaluasi. Setelah kondisi kembali, prosesor akan menerapkan hasil cabang yang sesuai dan membuang yang lain. Melakukan pekerjaan yang berpotensi tidak berguna di sini mungkin lebih baik daripada beralih ke utas yang berbeda, yang dapat menyebabkan meronta-ronta.

Karena kami telah beralih dari prosesor single-core berkecepatan tinggi clock ke prosesor multi-core, desain chip telah berfokus pada menjejalkan lebih banyak core per die, meningkatkan berbagi sumber daya on-chip antar core, algoritma prediksi cabang yang lebih baik, lebih baik beralih benang overhead, dan penjadwalan utas yang lebih baik.

IceArdor
sumber
hal yang sama dapat dilakukan dengan satu utas dan antrian: \ adakah benar-benar ada manfaatnya memiliki 80 utas pada 2-4 core, lebih dari hanya memiliki 2-4 core yang hanya memakan tugas dari antrian segera setelah mereka tiba dan mereka tidak ada hubungannya?
Dmitry
8

Sebagian besar jawaban di atas berbicara tentang kinerja dan operasi simultan. Saya akan mendekati ini dari sudut yang berbeda.

Mari kita ambil contoh program emulasi terminal yang sederhana. Anda harus melakukan hal-hal berikut:

  • perhatikan karakter yang masuk dari sistem jarak jauh dan tampilkan
  • perhatikan hal-hal yang datang dari keyboard dan kirimkan ke sistem jarak jauh

(Emulator terminal nyata melakukan lebih banyak, termasuk berpotensi menggemakan hal-hal yang Anda ketikkan pada layar juga, tetapi kami akan melewati itu untuk saat ini.)

Sekarang loop untuk membaca dari remote adalah sederhana, sesuai pseudocode berikut:

while get-character-from-remote:
    print-to-screen character

Loop untuk memantau keyboard dan pengiriman juga sederhana:

while get-character-from-keyboard:
    send-to-remote character

Masalahnya adalah Anda harus melakukan ini secara bersamaan. Kode sekarang harus terlihat lebih seperti ini jika Anda tidak memiliki threading:

loop:
    check-for-remote-character
    if remote-character-is-ready:
        print-to-screen character
    check-for-keyboard-entry
    if keyboard-is-ready:
        send-to-remote character

Logikanya, bahkan dalam contoh sederhana yang disengaja ini yang tidak memperhitungkan kompleksitas komunikasi dunia nyata, cukup dikaburkan. Dengan threading, bagaimanapun, bahkan pada satu inti, dua pseudocode loop dapat eksis secara independen tanpa menjalin logikanya. Karena kedua utas tersebut sebagian besar terikat I / O, mereka tidak menempatkan beban yang berat pada CPU, meskipun sebenarnya, lebih boros sumber daya CPU daripada loop terintegrasi.

Sekarang tentu saja penggunaan dunia nyata lebih rumit daripada yang di atas. Tetapi kompleksitas dari loop terintegrasi naik secara eksponensial saat Anda menambahkan lebih banyak kekhawatiran ke aplikasi. Logikanya semakin terfragmentasi dan Anda harus mulai menggunakan teknik seperti mesin negara, coroutine, dan lain-lain untuk mendapatkan hal-hal yang dapat dikelola. Dapat dikelola, tetapi tidak dapat dibaca. Threading membuat kode lebih mudah dibaca.

Jadi mengapa Anda tidak menggunakan threading?

Nah, jika tugas Anda terikat pada CPU bukannya I / O-terikat, threading sebenarnya memperlambat sistem Anda. Performa akan menderita. Banyak, dalam banyak kasus. ("Meronta-ronta" adalah masalah umum jika Anda menjatuhkan terlalu banyak utas terikat-CPU. Anda menghabiskan lebih banyak waktu mengubah utas aktif daripada menjalankan sendiri isi utas.) Juga, salah satu alasan logika di atas adalah begitu sederhana sehingga saya dengan sengaja memilih contoh yang simplistis (dan tidak realistis). Jika Anda ingin mengulangi apa yang diketik ke layar maka Anda memiliki dunia baru yang terluka saat Anda memperkenalkan penguncian sumber daya bersama. Dengan hanya satu sumber daya yang dibagikan ini tidak terlalu menjadi masalah, tetapi itu mulai menjadi masalah yang lebih besar dan lebih besar karena Anda memiliki lebih banyak sumber daya untuk dibagikan.

Jadi pada akhirnya, threading adalah tentang banyak hal. Sebagai contoh, ini tentang membuat proses I / O-terikat lebih responsif (meskipun secara keseluruhan kurang efisien) seperti yang telah dikatakan beberapa orang. Ini juga tentang membuat logika lebih mudah diikuti (tetapi hanya jika Anda meminimalkan keadaan bersama). Ini tentang banyak hal, dan Anda harus memutuskan apakah kelebihannya lebih besar daripada kerugiannya berdasarkan kasus per kasus.

HANYA PENDAPAT SAYA yang benar
sumber
6

Meskipun Anda tentu saja dapat menggunakan utas untuk mempercepat perhitungan tergantung pada perangkat keras Anda, salah satu kegunaan utama mereka adalah melakukan lebih dari satu hal sekaligus untuk alasan ramah pengguna.

Misalnya, jika Anda harus melakukan beberapa pemrosesan di latar belakang dan juga tetap responsif terhadap input UI, Anda dapat menggunakan utas. Tanpa utas, antarmuka pengguna akan hang setiap kali Anda mencoba melakukan pemrosesan yang berat.

Lihat juga pertanyaan terkait ini: Penggunaan praktis untuk utas

Cam
sumber
Penanganan UI adalah contoh klasik dari tugas yang terikat IO. Tidak baik memiliki satu inti CPU yang melakukan tugas pemrosesan dan IO.
Donal Fellows
6

Saya sangat tidak setuju dengan pernyataan @ kyoryu bahwa angka ideal adalah satu utas per CPU.

Pikirkan seperti ini: mengapa kita memiliki sistem operasi multi-pemrosesan? Untuk sebagian besar sejarah komputer, hampir semua komputer memiliki satu CPU. Namun sejak tahun 1960-an, semua komputer "nyata" memiliki sistem operasi multi-pemrosesan (alias multi-tasking).

Anda menjalankan banyak program sehingga satu dapat berjalan sementara yang lain diblokir untuk hal-hal seperti IO.

mari sisihkan argumen tentang apakah versi Windows sebelum NT multi-tasking. Sejak itu, setiap OS nyata memiliki multi-tasking. Beberapa tidak memaparkannya kepada pengguna, tetapi itu ada di sana, melakukan hal-hal seperti mendengarkan radio ponsel, berbicara dengan chip GPS, menerima input mouse, dll.

Utas hanyalah tugas yang sedikit lebih efisien. Tidak ada perbedaan mendasar antara tugas, proses, dan utas.

CPU adalah hal yang sangat buruk untuk disia-siakan, jadi siapkan banyak hal untuk menggunakannya ketika Anda bisa.

Saya akan setuju bahwa dengan sebagian besar bahasa prosedural, C, C ++, Java dll, menulis kode aman thread yang tepat adalah banyak pekerjaan. Dengan 6 core CPU yang ada di pasaran saat ini, dan 16 core CPU yang tidak jauh, saya berharap orang-orang akan menjauh dari bahasa-bahasa lama ini, karena multi-threading semakin banyak merupakan persyaratan penting.

Ketidaksepakatan dengan @kyoryu hanyalah IMHO, sisanya adalah fakta.

rekaman ikan
sumber
5
Jika Anda memiliki banyak utas yang terikat prosesor , maka angka yang ideal adalah satu per CPU (atau mungkin lebih sedikit, untuk membiarkan satu untuk mengelola semua I / O dan OS dan semua itu). Jika Anda memiliki utas terikat-IO , Anda dapat menumpuk cukup banyak pada satu CPU. Aplikasi yang berbeda memiliki campuran tugas prosesor-terikat dan IO yang berbeda; itu benar-benar alami, tetapi mengapa Anda harus berhati-hati dengan deklarasi universal.
Donal Fellows
1
Tentu saja, perbedaan paling penting antara utas dan proses adalah pada Windows tidak ada fork (), jadi proses pembuatannya benar-benar mahal, yang menyebabkan penggunaan ulir yang berlebihan.
ninjalj
Kecuali untuk pelipatan protein, SETI, dll. Tidak ada tugas pengguna praktis yang dihitung untuk waktu yang sangat lama. Selalu ada kebutuhan untuk mendapatkan info dari pengguna, berbicara dengan disk, berbicara dengan DBMS, dll. Ya, biaya fork () adalah salah satu dari banyak hal yang Cutler mengutuk NT dengan yang orang lain di DEC tahu.
Rekaman ikan
5

Bayangkan sebuah server Web yang harus melayani sejumlah permintaan sewenang-wenang. Anda harus melayani permintaan secara paralel karena jika tidak, setiap permintaan baru harus menunggu sampai semua permintaan lainnya selesai (termasuk mengirim respons melalui Internet). Dalam hal ini, sebagian besar server web memiliki core yang jauh lebih sedikit daripada jumlah permintaan yang biasanya mereka layani.

Ini juga memudahkan pengembang server: Anda hanya perlu menulis program utas yang melayani permintaan, Anda tidak perlu berpikir tentang menyimpan banyak permintaan, urutan yang Anda layani, dan sebagainya.

tobiw
sumber
2
Anda sedang menulis perangkat lunak untuk sistem operasi yang mendukung threading tetapi tidak memiliki kapasitas untuk multiplexing io? Saya pikir server web mungkin merupakan contoh buruk karena dalam hal ini multiplexing io hampir selalu akan lebih efisien daripada memunculkan lebih banyak utas daripada inti.
Jason Coco
3

Banyak utas akan tertidur, menunggu input pengguna, I / O, dan acara lainnya.

Anak anjing
sumber
Tentunya. cukup gunakan Task Manager pada Windows atau TOP pada OS nyata, dan lihat berapa banyak tugas / proses yang dilakukan. Selalu 90% atau lebih.
Rekaman ikan
2

Utas dapat membantu responsif dalam aplikasi UI. Selain itu, Anda dapat menggunakan utas untuk mendapatkan lebih banyak pekerjaan dari inti Anda. Misalnya, pada satu inti, Anda dapat memiliki satu utas melakukan IO dan lainnya melakukan beberapa perhitungan. Jika itu adalah single threaded, intinya bisa jadi idle menunggu IO selesai. Itu contoh level yang cukup tinggi, tetapi utas pasti dapat digunakan untuk memukul cpu Anda sedikit lebih keras.

Segera
sumber
Lebih khusus, satu utas dapat menunggu di I / O sementara yang lain melakukan perhitungan. Jika I / O mengambil (signifikan) siklus CPU, tidak akan ada untungnya menjalankannya di utas terpisah. Keuntungannya adalah benang komputasi Anda dapat berjalan sementara benang I / O Anda memutar-mutar ibu jarinya menunggu silinder aluminium besar berputar ke tempatnya, atau agar paket tiba di atas kawat dari Islandia, atau apa pun.
Ken
2

Prosesor, atau CPU, adalah chip fisik yang dicolokkan ke sistem. Sebuah prosesor dapat memiliki banyak inti (inti adalah bagian dari chip yang mampu menjalankan instruksi). Sebuah inti dapat muncul ke sistem operasi sebagai beberapa prosesor virtual jika mampu menjalankan secara bersamaan beberapa utas (utas adalah urutan instruksi tunggal).

Suatu proses adalah nama lain untuk suatu aplikasi. Secara umum, proses tidak tergantung satu sama lain. Jika satu proses mati, itu tidak menyebabkan proses lain juga mati. Dimungkinkan untuk proses berkomunikasi, atau berbagi sumber daya seperti memori atau I / O.

Setiap proses memiliki ruang alamat dan tumpukan yang terpisah. Suatu proses dapat berisi beberapa utas, masing-masing dapat menjalankan instruksi secara bersamaan. Semua utas dalam suatu proses berbagi ruang alamat yang sama, tetapi setiap utas akan memiliki tumpukannya sendiri.

Semoga dengan definisi ini dan penelitian lebih lanjut menggunakan dasar-dasar ini akan membantu pemahaman Anda.

Srikar Doddi
sumber
2
Saya tidak melihat bagaimana ini menjawab pertanyaannya sama sekali. Interpretasi saya atas pertanyaannya adalah tentang penggunaan utas inti dan penggunaan optimal sumber daya yang tersedia, atau tentang perilaku utas saat Anda menambah jumlahnya, atau sesuatu yang sejalan dengan itu.
David
@ David mungkin itu bukan jawaban langsung untuk pertanyaan saya, tapi saya masih merasa saya belajar dengan membacanya.
Nick Heiner
1

Penggunaan utas yang ideal sebenarnya adalah satu per inti.

Namun, kecuali Anda menggunakan IO asinkron / non-pemblokiran secara eksklusif, ada kemungkinan Anda akan memblokir utas pada suatu saat, yang tidak akan menggunakan CPU Anda.

Juga, bahasa pemrograman tipikal membuatnya agak sulit untuk menggunakan 1 utas per CPU. Bahasa yang dirancang di sekitar konkurensi (seperti Erlang) dapat membuatnya lebih mudah untuk tidak menggunakan utas tambahan.

Kyoryu
sumber
Menggunakan utas untuk tugas-tugas berkala adalah alur kerja yang sangat umum dan disambut baik, dan itu akan jauh dari ideal jika mereka mencuri sebuah inti.
Nick Bastin
@Nick Bastin: Ya, tapi lebih efisien untuk memasukkan tugas-tugas itu ke dalam antrian tugas dan menjalankannya dari antrian itu (atau strategi serupa). Untuk efisiensi optimal, 1 utas per inti mengalahkan semua, karena mencegah overhead dari pergantian konteks yang tidak perlu dan tumpukan tambahan dialokasikan. Tidak peduli apa pun, tugas periodik harus mencuri inti sementara 'aktif,' karena CPU hanya dapat benar-benar melakukan satu tugas per inti (ditambah hal-hal seperti hyperthreading jika tersedia).
Kyoryu
@Nick Bastin: Sayangnya, seperti yang saya katakan di jawaban utama, sebagian besar bahasa modern tidak cocok untuk menerapkan sistem yang melakukan ini secara efektif bukanlah hal yang sepele - Anda pada akhirnya melakukan sejumlah pertempuran melawan penggunaan khas bahasa tersebut.
Kyoryu
Maksud saya bukan bahwa satu utas per inti tidak optimal, itu satu utas per inti adalah mimpi pipa (kecuali Anda tertanam) dan merancang untuk mencoba menekannya adalah buang-buang waktu, jadi Anda mungkin juga lakukan apa yang membuatnya mudah bagi Anda (dan bagaimanapun juga tidak efisien pada penjadwal modern), daripada mencoba mengoptimalkan jumlah utas yang Anda gunakan. Haruskah kita memutar benang tanpa alasan yang jelas? Tentu saja tidak, tetapi apakah Anda membuang-buang sumber daya komputer yang tidak perlu adalah masalah terlepas dari threading.
Nick Bastin
@Nick Bastin: Jadi, untuk meringkas, satu utas per inti adalah ideal, tetapi sebenarnya mencapai itu tidak terlalu mungkin. Saya mungkin seharusnya lebih kuat daripada 'agak sulit' ketika berbicara tentang seberapa besar kemungkinan untuk benar-benar mencapai hal seperti itu.
Kyoryu
1

Cara beberapa API dirancang, Anda tidak punya pilihan selain menjalankannya di utas terpisah (apa pun dengan operasi pemblokiran). Contohnya adalah pustaka HTTP Python (AFAIK).

Biasanya ini bukan masalah besar (jika itu adalah masalah, OS atau API harus dikirimkan dengan mode operasi asinkron alternatif, yaitu:) select(2), karena itu mungkin berarti utas akan tertidur selama menunggu I / O selesai. Di sisi lain, jika ada sesuatu yang melakukan perhitungan berat, Anda harus meletakkannya di utas terpisah daripada mengatakan, utas GUI (kecuali jika Anda menikmati multiplexing manual).

L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
sumber
1

Saya tahu ini adalah pertanyaan yang sangat lama dengan banyak jawaban bagus, tetapi saya di sini untuk menunjukkan sesuatu yang penting dalam lingkungan saat ini:

Jika Anda ingin merancang aplikasi untuk multi-threading, Anda tidak boleh mendesain untuk pengaturan perangkat keras tertentu. Teknologi CPU telah maju cukup cepat selama bertahun-tahun, dan jumlah inti terus meningkat. Jika Anda sengaja mendesain aplikasi sehingga hanya menggunakan 4 utas, maka Anda berpotensi membatasi diri dalam sistem octa-core (misalnya). Sekarang, bahkan sistem 20-inti tersedia secara komersial, sehingga desain seperti itu jelas lebih banyak merugikan daripada menguntungkan.

Jai
sumber
0

Menanggapi dugaan pertama Anda: mesin multi-core dapat secara bersamaan menjalankan beberapa proses, bukan hanya beberapa utas dari satu proses.

Menanggapi pertanyaan pertama Anda: titik beberapa utas biasanya untuk secara bersamaan melakukan beberapa tugas dalam satu aplikasi. Contoh klasik di internet adalah program email yang mengirim dan menerima surat, dan server web menerima dan mengirim permintaan halaman. (Perhatikan bahwa pada dasarnya tidak mungkin untuk mengurangi sistem seperti Windows untuk menjalankan hanya satu utas atau bahkan hanya satu proses. Jalankan Windows Task Manager dan Anda biasanya akan melihat daftar panjang proses aktif, banyak di antaranya akan menjalankan beberapa utas. )

Menanggapi pertanyaan kedua Anda: sebagian besar proses / utas tidak terikat-CPU (yaitu, tidak berjalan terus-menerus dan tidak terputus), tetapi sebaliknya berhenti dan tunggu sering sampai I / O selesai. Selama menunggu itu, proses / utas lainnya dapat berjalan tanpa "mencuri" dari kode tunggu (bahkan pada mesin inti tunggal).

joe snyder
sumber
-5

Sebuah utas adalah abstraksi yang memungkinkan Anda untuk menulis kode sesederhana urutan operasi, dengan bahagia tidak menyadari bahwa kode tersebut dieksekusi bertautan dengan kode lain, atau diparkir menunggu IO, atau (mungkin agak lebih sadar) menunggu utas lainnya. acara atau pesan.

KarlP
sumber
Saya mungkin telah mengedit ini dengan menambahkan lebih banyak contoh sejak downvotes - tetapi utas (atau proses, dalam konteks ini hampir tidak ada perbedaan) tidak ditemukan untuk meningkatkan kinerja, melainkan untuk menyederhanakan kode asinkron dan menghindari penulisan mesin negara yang rumit yang harus menangani semua kondisi super yang mungkin dalam program. Bahkan biasanya ada satu CPU bahkan di server besar. Saya, hanya ingin tahu mengapa jawaban saya dianggap anti-membantu?
KarlP
-8

Intinya adalah bahwa sebagian besar programmer tidak mengerti bagaimana merancang mesin negara. Mampu meletakkan segala sesuatu di utasnya sendiri membebaskan programmer dari harus berpikir tentang bagaimana secara efisien mewakili keadaan dari berbagai perhitungan dalam proses sehingga mereka dapat diinterupsi dan kemudian dilanjutkan.

Sebagai contoh, pertimbangkan kompresi video, tugas yang sangat intensif CPU. Jika Anda menggunakan alat gui, Anda mungkin ingin antarmuka tetap responsif (tampilkan kemajuan, jawab untuk membatalkan permintaan, ukuran jendela, dll.). Jadi Anda mendesain perangkat lunak pembuat enkode Anda untuk memproses unit besar (satu atau lebih frame) sekaligus dan menjalankannya di utasnya sendiri, terpisah dari UI.

Tentu saja setelah Anda menyadari bahwa akan lebih baik untuk dapat menyimpan status penyandian yang sedang berlangsung sehingga Anda dapat menutup program untuk mem-boot ulang atau memainkan game yang haus sumber daya, Anda menyadari bahwa Anda seharusnya belajar bagaimana merancang mesin negara dari awal. Entah itu, atau Anda memutuskan untuk merekayasa masalah baru seluruh proses hibernasi OS Anda sehingga Anda dapat menangguhkan dan melanjutkan aplikasi individual ke disk ...

R .. GitHub BERHENTI MEMBANTU ICE
sumber
7
Tidak (cukup!) Bernilai -1, tapi serius, itu tentang hal yang paling bodoh yang pernah saya dengar dari orang lain mengenai hal ini. Saya, misalnya, tidak memiliki masalah dalam menerapkan mesin negara. Tidak sama sekali. Saya hanya tidak suka menggunakannya ketika alat lain ada yang meninggalkan lebih jelas dan lebih mudah untuk mempertahankan kode. Mesin-mesin negara memiliki tempat mereka, dan di tempat-tempat itu mereka tidak dapat ditandingi. Menggabungkan operasi intensif CPU dengan pembaruan GUI bukan salah satu dari tempat-tempat itu. Setidaknya coroutine adalah pilihan yang lebih baik di sana, dengan threading menjadi lebih baik.
HANYA SAYA PENDAPAT benar
Untuk semua orang yang mengubah jawaban saya, ini BUKAN argumen yang menentang penggunaan utas! Jika Anda dapat membuat kode mesin negara yang hebat, dan tentu saja masuk akal untuk menjalankan mesin negara dalam utas terpisah bahkan jika Anda tidak harus melakukannya. Komentar saya adalah bahwa sering kali pilihan untuk menggunakan utas dibuat terutama dari keinginan untuk menghindari mendesain mesin-mesin negara, yang oleh banyak programmer dianggap "terlalu keras", daripada untuk keuntungan lainnya.
R .. GitHub BERHENTI MEMBANTU ICE