Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Artikel ini menyediakan informasi yang akan membantu Anda menulis kueri PLINQ yang seefisien mungkin sambil tetap menghasilkan hasil yang benar.
Tujuan utama PLINQ adalah untuk mempercepat eksekusi kueri LINQ ke Objek dengan menjalankan delegasi kueri secara paralel pada komputer multi-inti. PLINQ berkinerja terbaik ketika pemrosesan setiap elemen dalam koleksi sumber bersifat mandiri, tanpa adanya status bersama yang terlibat di antara masing-masing delegasi. Operasi semacam itu umum dalam LINQ ke Objek dan PLINQ, dan sering disebut "dengan cara yang paralel dan menyenangkan" karena mereka memungkinkan penjadwalan yang mudah pada beberapa utas. Namun, tidak semua kueri sepenuhnya terdiri dari operasi paralel yang menyenangkan. Dalam kebanyakan kasus, kueri melibatkan beberapa operator yang tidak dapat diparalelkan, atau yang memperlambat eksekusi paralel. Dan bahkan dengan kueri yang sepenuhnya paralel, PLINQ harus tetap mempartisi sumber data dan menjadwalkan pekerjaan pada utas, dan biasanya menggabungkan hasil ketika kueri selesai. Semua operasi ini menambah biaya komputasi paralelisasi; biaya penambahan paralelisasi ini disebut overhead. Untuk mencapai performa optimal dalam kueri PLINQ, tujuannya adalah untuk memaksimalkan bagian yang berjalan secara paralel dan meminimalkan bagian yang memerlukan overhead.
Faktor-faktor yang Memengaruhi Performa Kueri PLINQ
Bagian berikut mencantumkan beberapa faktor terpenting yang memengaruhi performa kueri paralel. Ini adalah pernyataan umum yang dengan sendirinya tidak cukup untuk memprediksi performa kueri dalam semua kasus. Seperti biasa, penting untuk mengukur performa aktual kueri tertentu di komputer dengan berbagai konfigurasi dan beban perwakilan.
Biaya komputasi dari keseluruhan pekerjaan.
Untuk mencapai speedup, kueri PLINQ harus memiliki pekerjaan paralel yang cukup menyenangkan untuk mengimbangi overhead. Pekerjaan dapat dinyatakan sebagai biaya komputasi dari setiap delegasi dikalikan dengan jumlah elemen dalam koleksi sumber. Dengan asumsi bahwa operasi dapat diparalelkan, semakin mahal secara komputasi, semakin besar peluang untuk percepatan. Misalnya, jika fungsi membutuhkan satu milidetik untuk dijalankan, kueri berurutan lebih dari 1000 elemen akan memakan waktu satu detik untuk melakukan operasi tersebut, sedangkan kueri paralel pada komputer dengan empat inti mungkin hanya memakan waktu 250 milidetik. Ini menghasilkan kecepatan 750 milidetik. Jika fungsi memerlukan satu detik untuk dijalankan untuk setiap elemen, maka speedup akan menjadi 750 detik. Jika delegate sangat mahal, maka PLINQ mungkin menawarkan peningkatan kecepatan yang signifikan hanya dengan beberapa item dalam koleksi sumber. Sebaliknya, koleksi sumber kecil dengan delegasi sepele umumnya bukan kandidat yang baik untuk PLINQ.
Dalam contoh berikut, queryA mungkin adalah kandidat yang baik untuk PLINQ, dengan asumsi bahwa fungsi Pilih melibatkan banyak pekerjaan. queryB mungkin bukan kandidat yang baik karena tidak ada cukup pekerjaan dalam pernyataan SELECT, dan overhead paralelisasi akan mengimbangi sebagian besar atau semua peningkatan kecepatan.
Dim queryA = From num In numberList.AsParallel() Select ExpensiveFunction(num); 'good for PLINQ Dim queryB = From num In numberList.AsParallel() Where num Mod 2 > 0 Select num; 'not as good for PLINQvar queryA = from num in numberList.AsParallel() select ExpensiveFunction(num); //good for PLINQ var queryB = from num in numberList.AsParallel() where num % 2 > 0 select num; //not as good for PLINQJumlah inti logis pada sistem (tingkat paralelisme).
Titik ini adalah konsekuensi yang jelas dari bagian sebelumnya, kueri yang berjalan paralel lebih cepat pada mesin dengan lebih banyak inti karena pekerjaan dapat dibagi di antara lebih banyak utas secara bersamaan. Jumlah percepatan keseluruhan tergantung pada persentase pekerjaan kueri secara keseluruhan yang dapat diparalelkan. Namun, jangan berasumsi bahwa semua kueri akan berjalan dua kali lebih cepat pada komputer delapan inti daripada komputer empat inti. Saat menyetel kueri untuk performa optimal, penting untuk mengukur hasil aktual pada komputer dengan berbagai jumlah inti. Titik ini terkait dengan titik #1: himpunan data yang lebih besar diperlukan untuk memanfaatkan sumber daya komputasi yang lebih besar.
Jumlah dan jenis operasi.
PLINQ menyediakan operator AsOrdered untuk situasi di mana perlu untuk mempertahankan urutan elemen dalam urutan sumber. Ada biaya yang terkait dengan pemesanan, tetapi biaya ini biasanya sederhana. Operasi GroupBy dan Join juga menimbulkan overhead. PLINQ berkinerja terbaik ketika diizinkan untuk memproses elemen dalam koleksi sumber dalam urutan apa pun, dan meneruskannya ke operator berikutnya segera setelah siap. Untuk informasi selengkapnya, lihat Pelestarian Pesanan di PLINQ.
Bentuk pelaksanaan kueri.
Jika Anda menyimpan hasil kueri dengan memanggil ToArray atau ToList, maka hasil dari semua utas paralel harus digabungkan ke dalam struktur data tunggal. Ini melibatkan biaya komputasi yang tidak dapat ditolak. Demikian juga, jika Anda melakukan iterasi hasil dengan menggunakan perulangan foreach (Untuk Setiap di Visual Basic), hasil dari utas pekerja perlu diserialisasikan ke utas enumerator. Tetapi jika Anda hanya ingin melakukan beberapa tindakan berdasarkan hasil dari setiap utas, Anda dapat menggunakan metode ForAll untuk melakukan pekerjaan ini pada beberapa utas.
Jenis opsi penggabungan.
PLINQ dapat dikonfigurasi untuk mem-buffer keluarannya, dan menghasilkannya dalam potongan-potongan atau sekaligus setelah seluruh set hasil diproduksi, atau untuk mengalirkan hasil per individu saat diproduksi. Yang pertama menghasilkan penurunan waktu eksekusi keseluruhan dan yang terakhir menghasilkan penurunan latensi antara elemen yang dihasilkan. Meskipun opsi penggabungan tidak selalu berdampak besar pada performa kueri secara keseluruhan, opsi tersebut dapat memengaruhi performa yang dirasakan karena mereka mengontrol berapa lama pengguna harus menunggu untuk melihat hasil. Untuk informasi selengkapnya, lihat Opsi Penggabungan di PLINQ.
Jenis partisi.
Dalam beberapa kasus, kueri PLINQ melalui kumpulan sumber yang dapat diindeks dapat mengakibatkan beban kerja yang tidak seimbang. Saat ini terjadi, Anda mungkin dapat meningkatkan performa kueri dengan membuat partisi kustom. Untuk informasi selengkapnya, lihat Pemartisi Kustom untuk PLINQ dan TPL.
Saat PLINQ Memilih Mode Berurutan
PLINQ akan selalu mencoba menjalankan kueri setidaknya secepat kueri akan berjalan secara berurutan. Meskipun PLINQ tidak melihat seberapa mahal komputasi delegasi pengguna, atau seberapa besar sumber input, itu mencari "bentuk" kueri tertentu. Secara khusus, ia mencari operator kueri atau kombinasi operator yang biasanya menyebabkan kueri dijalankan lebih lambat dalam mode paralel. Ketika menemukan bentuk seperti itu, PLINQ secara default kembali ke mode berurutan.
Namun, setelah mengukur performa kueri tertentu, Anda dapat menentukan bahwa kueri tersebut benar-benar berjalan lebih cepat dalam mode paralel. Dalam kasus seperti itu, Anda dapat menggunakan flag melalui metode ParallelExecutionMode.ForceParallelismWithExecutionMode untuk menginstruksikan PLINQ untuk memparallelisasi kueri. Untuk informasi selengkapnya, lihat Cara: Menentukan Mode Eksekusi di PLINQ.
Daftar berikut ini menjelaskan bentuk kueri yang akan dijalankan PLINQ secara default dalam mode berurutan:
Kueri yang berisi klausa Select, indexed Where, indexed SelectMany, atau ElementAt setelah operator pemesanan atau pemfilteran yang telah menghapus atau mengatur ulang indeks asli.
Kueri yang berisi operator Take, TakeWhile, Skip, SkipWhile dan di mana indeks dalam urutan sumber tidak dalam urutan asli.
Kueri yang berisi Zip atau SequenceEquals, kecuali salah satu sumber data memiliki indeks yang awalnya diurutkan dan sumber data lainnya dapat diindeks (yaitu array atau IList(T)).
Kueri yang berisi Concat, kecuali diterapkan ke sumber data yang dapat diindeks.
Kueri yang berisi Pembalikan, kecuali diterapkan ke sumber data yang dapat diindeks.