Apa yang merupakan penggunaan thread yang tepat dalam pemrograman?


13

Saya lelah mendengar orang merekomendasikan Anda harus menggunakan hanya satu utas per prosesor, sementara banyak program menggunakan hingga 100 per proses! ambil contoh beberapa program umum

vb.net ide uses about 25 thread when not debugging
System uses about 100
chrome uses about 19
Avira uses more than about 50

Setiap kali saya memposting pertanyaan terkait thread, saya diingatkan hampir setiap kali saya tidak boleh menggunakan lebih dari satu thread per prosesor, dan semua program yang saya sebutkan di atas merusak sistem saya dengan prosesor tunggal.


7
Rekomendasi itu untuk luas. Batas satu utas per prosesor hanya sesuai untuk aplikasi yang terikat secara komputasi. Sebagian besar program terikat IO, baik itu lalu lintas jaringan, akses disk, atau bahkan RAM. Itu sebabnya server web, database, dll. Memiliki kumpulan utas dengan lebih banyak utas daripada inti prosesor.
Kilian Foth

2
"Saya diingatkan hampir setiap kali saya tidak boleh menggunakan lebih dari satu utas per prosesor"? Bisakah Anda memposting tautan atau contoh? Hampir setiap waktu?
S.Lott

2
"... orang-orang merekomendasikan Anda hanya menggunakan satu utas per proses." Siapakah orang-orang ini? Penjadwalan telah meningkat secara signifikan sejak Abad Kegelapan.
Rein Henrichs

2
Anda tidak boleh memiliki lebih dari satu utas UI per proses.
SLaks

3
@Billy ONeal, hasil edit Anda membuat pertanyaan tidak ada artinya
SK-logic

Jawaban:


22

Anda harus menggunakan hanya satu utas per prosesor,

Mungkin di HPC di mana Anda ingin efisiensi maksimum - tetapi sebaliknya hal paling bodoh yang saya dengar hari ini!

Anda harus menggunakan jumlah utas yang sesuai untuk desain program dan masih memberikan kinerja yang dapat diterima.

Untuk server web, mungkin masuk akal untuk mengaktifkan utas untuk setiap koneksi yang masuk (walaupun ada cara yang lebih baik untuk server yang sangat sarat muatan).

Untuk sebuah ide, setiap alat yang berjalan di utasnya sendiri tidak masuk akal. Saya menduga banyak utas yang dilaporkan untuk .Net IDE adalah hal-hal seperti pencatatan dan tugas I / O yang dimulai pada utas mereka sendiri sehingga mereka dapat terus tidak terblokir.


9
Sekarang Anda membuat saya bertanya-tanya apa hal paling bodoh yang pernah Anda dengar!
Michael K

3
@Michael - Saya sudah mengajar undergrads dan bekerja di kontrak pertahanan - Anda tidak akan percaya hal paling bodoh yang pernah saya dengar!
Martin Beckett

1
Sudahkah kita melihatnya di TheDailyWTF.com?
FrustratedWithFormsDesigner

saya tidak dapat menemukan mereka sekarang, tetapi lihat tautan ini social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/…
Smith

2
Miliki paling banyak satu utas terikat CPU per prosesor yang dialokasikan untuk aplikasi. Utas terikat-IO bukan masalah besar (selain memori yang mereka konsumsi) dan penting untuk diingat bahwa aplikasi dapat dibatasi hanya menggunakan subset CPU sistem; setelah semua, itu (biasanya) komputer pengguna / admin dan bukan programmer.
Donal Fellows

2

Nasihat one-thread-per-core berlaku ketika tujuannya adalah mempercepat melalui eksekusi paralel.

Alasan yang sama sekali berbeda dan sama-sama valid adalah kesederhanaan kode ketika harus menanggapi peristiwa yang tidak terduga. Jadi jika suatu program harus mendengarkan pada 100 soket, dan tampaknya memberikan perhatian penuh kepada masing-masing, itu adalah penggunaan yang sempurna untuk threading. Contoh lain adalah UI, di mana satu utas menangani acara UI, sementara yang lain memproses latar belakang.


1
Pemrosesan yang terikat IO dapat dilakukan sebagai satu utas per sumber acara, atau beberapa sumber acara dapat digandakan ke satu utas. Kode multipleks biasanya lebih kompleks dan lebih efisien.
Donal Fellows

2

Anda menginginkan satu utas untuk setiap perhitungan yang dapat dilanjutkan dengan laju yang berbeda dari perhitungan lainnya.

Untuk komputasi paralel yang terikat CPU, yang datang dalam blok kerja besar, Anda biasanya menginginkan satu utas per CPU, karena begitu semuanya sibuk, lebih banyak utas tidak membantu dan hanya membuat overhead scheduler. Jika blok pekerjaan memiliki ukuran tidak teratur dalam waktu, atau dihasilkan secara dinamis saat runtime (sering terjadi ketika Anda memiliki struktur data kompleks yang besar untuk diproses), Anda mungkin ingin melampirkan blok-blok itu ke banyak utas, sehingga penjadwal selalu memiliki besar atur untuk memilih dari ketika beberapa blok kerja selesai, untuk membuat semua CPU sibuk.

Untuk perhitungan terikat I / O, Anda biasanya menginginkan satu utas untuk setiap "saluran" I / O independen karena mereka berkomunikasi pada tingkat yang berbeda, dan utas diblokir pada saluran kemudian tidak mencegah utas lainnya untuk membuat kemajuan.


Perlu diketahui bahwa gaya threading ini dapat menyebabkan beberapa program yang dirancang khusus. Saya telah melihat sebuah program 4-utas yang memiliki utas untuk membaca catatan dari tabel DB, utas untuk menulis catatan bertransformasi ke soket, utas untuk membaca jawaban atas soket tulis itu (yang kembali rusak) dan asinkron), dan utas untuk mengubah catatan DB asli dengan jawabannya. Kondisi kesalahan yang tidak diinginkan terjadi.
Bruce Ediger

Satu pandangan adalah bahwa gaya ini menghasilkan program aneh. Pandangan lain adalah ini gaya alami yang seharusnya dimiliki program. Tidak tahu tentang kondisi kesalahan "tidak intuitif"; jika Anda memiliki banyak hal yang terjadi, dan salah satu dari mereka mendapat kesalahan, memastikan itu disebarkan dengan benar di seluruh perhitungan asinkron adalah masalah bagi banyak bahasa [bodohnya, pengecualian Java tidak didefinisikan pada batas-batas utas], tetapi tidak masalah dengan gaya program. (Bahasa pemrograman PARLANSE kami [lihat bio saya] menangani pengecualian lintas batas thread secara bersih sehingga dimungkinkan untuk melakukan ini dengan benar.).
Ira Baxter

1

Aturan praktis untuk utas adalah, Anda ingin setidaknya satu "aktif" (mampu menjalankan perintahnya segera diberikan waktu CPU) utas pekerja untuk setiap "unit eksekusi" yang tersedia di komputer. "Unit eksekusi" adalah salah satu prosesor instruksi logis, sehingga server quad-chip, quad-core Xeon hyperthreaded akan memiliki 32 EU (4 chip, 4 core per chip, masing-masing hyperthreaded). Core i7 rata-rata Anda akan memiliki 8.

Satu utas per UE adalah penggunaan daya CPU sepenuhnya, dengan ketentuan bahwa utas akan selalu dalam keadaan berjalan; ini hampir tidak pernah terjadi, karena utas membutuhkan akses ke memori yang tidak di-cache, hard disk, port jaringan, dll. yang harus mereka tunggu, dan yang tidak memerlukan perhatian CPU aktif untuk melakukan. Dengan demikian, Anda dapat lebih meningkatkan efisiensi secara keseluruhan dengan lebih banyak utas yang disiapkan dan siap untuk digunakan. Ini memang perlu biaya; ketika sebuah CPU mengganti sebuah thread, ia harus menyimpan cache dari register thread, pointer eksekusi dan info status lainnya yang biasanya disimpan di tempat kerja terdalam dari UE dan diakses dengan sangat cepat, memungkinkan UE lain dalam chip CPU untuk mengambilnya. Ini juga membutuhkan utas di OS untuk memutuskan utas mana yang harus dialihkan. Terakhir, ketika UE mengganti utas, kehilangan keuntungan kinerja pipelining yang digunakan kebanyakan arsitektur prosesor; itu harus menyiram pipa sebelum beralih benang. Tetapi, karena semua ini masih memakan waktu jauh lebih sedikit daripada rata-rata hanya menunggu hard drive atau bahkan RAM untuk kembali dengan informasi, itu sepadan dengan biayanya.

Namun, secara umum, setelah Anda melampaui dua kali jumlah utas "aktif" seperti UE, OS mulai menghabiskan lebih banyak utas penjadwalan waktu UE, dan UE menghabiskan lebih banyak waktu untuk beralih di antara mereka, daripada yang sebenarnya dihabiskan dengan menjalankan utas aktif program. Ini adalah titik skala diseconomies; sebenarnya akan memakan waktu lebih lama untuk menjalankan algoritma multithreaded jika Anda menambahkan utas tambahan pada saat ini.

Jadi, secara keseluruhan, Anda ingin mempertahankan setidaknya sebanyak utas dalam program Anda seperti halnya Anda memiliki UE di komputer, tetapi Anda ingin menghindari memiliki lebih dari dua kali lipat jumlah yang tidak menunggu atau tidur.


Jika N adalah jumlah utas dan U jumlah unit, OP mempertanyakan aturan "N = U". Anda mengendurkannya dengan aturan "U <= N <= 2 U". Saya akan melangkah lebih jauh dan mengatakan bahwa "N <= c U" untuk konstanta "cukup kecil" (diketahui oleh programmer) c dapat diterima (jika tolok ukur menunjukkan kinerja yang wajar). Saya akan sangat khawatir jika jumlah utas dapat tumbuh ke jumlah yang berpotensi tidak terbatas.
5gon12eder

1

Anda harus menggunakan satu utas untuk:

Setiap prosesor Anda harus tetap sibuk.

Setiap I / O yang dapat Anda gunakan secara bersamaan secara bersamaan tidak dapat Anda lakukan dengan cara yang tidak menghalangi. (Misalnya, membaca dari disk lokal.)

Setiap tugas yang memerlukan utas khusus, misalnya memanggil ke perpustakaan yang tidak memiliki antarmuka non-pemblokiran atau di mana antarmuka non-pemblokiran tidak sesuai. Ini termasuk tugas-tugas seperti memonitor jam sistem, menyalakan timer, dan sebagainya.

Beberapa tambahan untuk melindungi dari pemblokiran yang tidak terduga seperti kesalahan halaman.

Beberapa tambahan untuk melindungi terhadap pemblokiran yang diharapkan yang tidak perlu dioptimalkan, misalnya dalam kode tidak kritis. (Misalnya, jika Anda mungkin sangat jarang perlu melakukan permintaan DNS, itu mungkin tidak sebanding dengan upaya untuk melakukan permintaan DNS secara tidak sinkron. Cukup buat beberapa utas tambahan dan buat hidup Anda lebih mudah.)

Jika Anda mengikuti aturan "satu utas per prosesor", maka semua kode Anda kritis terhadap kinerja. Kode apa pun yang memblokir karena alasan tertentu berarti proses Anda tidak dapat menggunakan prosesor itu. Itu membuat pemrograman jauh lebih sulit tanpa alasan.


0

Anda dapat memunculkan proses dan utas untuk memungkinkan pemanfaatan sistem multicore \ multiprosesor untuk satu program di mana Anda tidak mendapat manfaat (untuk setidaknya satu program) dari memiliki lebih banyak proses \ utas kemudian inti.

Atau Anda dapat memiliki rutinitas jajak pendapat untuk acara yang biasanya memblokir eksekusi lebih lanjut. Alih-alih mengikat CPU dengan polling, Anda bisa membuat utas yang akan duduk dalam keadaan diam sampai acara yang tepat membangunkannya. Metode ini sangat umum digunakan di server web, dan antrian acara GUI. Sebagian besar program ingin memiliki semacam penyimpanan data pusat (bahkan jika kode eksekusi programnya) yang dapat diakses oleh semua utas, jadi saya rasa itu sebabnya mereka menggunakan proses threading.


0

Aplikasi yang Anda sebutkan jarang menjalankan semua utas secara bersamaan. Sebagian besar dari mereka hanya duduk di sana karena mereka berada di kolam utas . Aplikasi mengirim berbagai tugas ke antrian, yang dibersihkan oleh utas di kumpulan utas.

Mengapa ukuran kolam begitu besar? Karena, sering utas harus menunggu sumber lain seperti disk, jaringan, pengguna, beberapa utas lainnya, dll. Sementara utas sedang menunggu, sebaiknya jalankan utas lain untuk sepenuhnya memanfaatkan prosesor. Mengukur ukuran kolam dengan tepat memang sulit. Terlalu sedikit utas, dan Anda akan kehilangan kinerja karena prosesor tidak sepenuhnya digunakan saat menunggu sesuatu. Terlalu banyak utas, dan Anda akan kehilangan kinerja karena beralih di antara mereka.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.