Yang pertama adalah pilihan yang jauh lebih baik.
Parallel.ForEach, secara internal, menggunakan a Partitioner<T>
untuk mendistribusikan koleksi Anda ke item pekerjaan. Itu tidak akan melakukan satu tugas per item, tetapi batch ini untuk menurunkan overhead yang terlibat.
Opsi kedua akan menjadwalkan satu Task
per item dalam koleksi Anda. Walaupun hasilnya akan (hampir) sama, ini akan menghasilkan overhead yang jauh lebih banyak dari yang diperlukan, terutama untuk koleksi besar, dan menyebabkan runtime keseluruhan menjadi lebih lambat.
FYI - Partisi yang digunakan dapat dikontrol dengan menggunakan overload yang sesuai ke Paralel. Untuk Setiap , jika diinginkan. Untuk detailnya, lihat Pemisah Kustom di MSDN.
Perbedaan utama, pada saat runtime, adalah yang kedua akan bertindak asinkron. Ini dapat diduplikasi menggunakan Paralel. FOREach dengan melakukan:
Task.Factory.StartNew( () => Parallel.ForEach<Item>(items, item => DoSomething(item)));
Dengan melakukan ini, Anda masih mengambil keuntungan dari partisi, tetapi jangan memblokir sampai operasi selesai.
Saya melakukan percobaan kecil menjalankan metode "1.000.000.000 (satu miliar)" kali dengan "Paralel. Untuk" dan satu dengan objek "Tugas".
Saya mengukur waktu prosesor dan menemukan Paralel lebih efisien. Paralel. Untuk membagi tugas Anda menjadi beberapa item kerja kecil dan menjalankannya pada semua core secara paralel dengan cara yang optimal. Saat membuat banyak objek tugas (FYI TPL akan menggunakan thread pooling secara internal) akan memindahkan setiap eksekusi pada setiap tugas yang menciptakan lebih banyak tekanan di dalam kotak yang terbukti dari percobaan di bawah ini.
Saya juga telah membuat video kecil yang menjelaskan TPL dasar dan juga mendemonstrasikan bagaimana Parallel.For menggunakan inti Anda dengan lebih efisien http://www.youtube.com/watch?v=No7QqSc5cl8 dibandingkan dengan tugas dan utas normal.
Eksperimen 1
Eksperimen 2
sumber
Mehthod1()
dilakukan dalam contoh ini?Parallel.ForEach akan mengoptimalkan (bahkan mungkin tidak memulai utas baru) dan memblokir sampai loop selesai, dan Task.Factory akan secara eksplisit membuat instance tugas baru untuk setiap item, dan kembali sebelum selesai (tugas tidak sinkron). Parallel.Foreach jauh lebih efisien.
sumber
Dalam pandangan saya, skenario yang paling realistis adalah ketika tugas harus diselesaikan dengan berat. Pendekatan Shivprasad lebih berfokus pada penciptaan objek / alokasi memori daripada pada komputasi itu sendiri. Saya melakukan penelitian dengan memanggil metode berikut:
Eksekusi metode ini memakan waktu sekitar 0,5 detik.
Saya menyebutnya 200 kali menggunakan Paralel:
Lalu saya menyebutnya 200 kali menggunakan cara kuno:
Kasus pertama selesai dalam 26656ms, yang kedua dalam 24478ms. Saya mengulanginya berkali-kali. Setiap kali pendekatan kedua marjinal lebih cepat.
sumber