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.
Jawaban:
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.
sumber
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.
sumber
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.
sumber
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.
sumber
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.
sumber
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.
sumber
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.
sumber