Saya suka banyak vektor. Mereka bagus dan cepat. Tapi saya tahu benda yang disebut valarray ini ada. Mengapa saya menggunakan valarray bukan vektor? Saya tahu valarrays memiliki sedikit gula sintaksis, tetapi selain itu, kapan mereka berguna?
159
valarray
sini dan di siniJawaban:
Valarrays (array nilai) dimaksudkan untuk membawa beberapa kecepatan Fortran ke C ++. Anda tidak akan membuat pointer valarray sehingga kompiler dapat membuat asumsi tentang kode dan mengoptimalkannya dengan lebih baik. (Alasan utama bahwa Fortran begitu cepat adalah karena tidak ada tipe pointer sehingga tidak ada pointer alias.)
Valarrays juga memiliki kelas-kelas yang memungkinkan Anda untuk mengirisnya dengan cara yang cukup mudah meskipun bagian dari standar itu dapat menggunakan sedikit lebih banyak pekerjaan. Mengubah ukuran mereka merusak dan mereka kekurangan iterator.
Jadi, jika itu angka yang Anda gunakan dan kenyamanan bukan yang terpenting gunakan valarrays. Kalau tidak, vektor jauh lebih nyaman.
sumber
valarray
adalah jenis anak yatim yang lahir di tempat yang salah pada waktu yang salah. Ini merupakan upaya optimasi, cukup khusus untuk mesin yang digunakan untuk matematika tugas berat ketika ditulis - khususnya, prosesor vektor seperti Crays.Untuk prosesor vektor, yang biasanya ingin Anda lakukan adalah menerapkan satu operasi ke seluruh array, lalu menerapkan operasi berikutnya ke seluruh array, dan seterusnya hingga Anda melakukan semua yang perlu Anda lakukan.
Namun, kecuali Anda berurusan dengan array yang cukup kecil, itu cenderung bekerja dengan buruk dengan caching. Pada kebanyakan mesin modern, apa yang umumnya Anda sukai (sebisa mungkin) adalah memuat bagian dari array, melakukan semua operasi yang Anda inginkan, kemudian pindah ke bagian berikutnya dari array.
valarray
juga diharapkan untuk menghilangkan kemungkinan aliasing, yang (setidaknya secara teoritis) memungkinkan kompiler meningkatkan kecepatan karena lebih bebas untuk menyimpan nilai dalam register. Pada kenyataannya, bagaimanapun, saya sama sekali tidak yakin bahwa implementasi nyata memanfaatkan ini ke tingkat yang signifikan. Saya curiga ini semacam masalah ayam-dan-telur - tanpa dukungan kompiler, itu tidak menjadi populer, dan selama itu tidak populer, tidak ada yang akan bersusah payah mengerjakan kompiler mereka untuk mendukungnya.Ada juga berbagai kelas tambahan yang membingungkan untuk digunakan dengan valarray. Anda mendapatkan
slice
,slice_array
,gslice
dangslice_array
bermain dengan potongan-potongan darivalarray
, dan membuatnya bertindak seperti array multi-dimensi. Anda jugamask_array
dapat "menutupi" operasi (mis. Tambahkan item dalam x ke y, tetapi hanya pada posisi di mana z bukan nol). Untuk membuat lebih dari penggunaan sepelevalarray
, Anda harus belajar banyak tentang kelas tambahan ini, beberapa di antaranya cukup kompleks dan tidak ada yang tampaknya (setidaknya bagi saya) didokumentasikan dengan sangat baik.Intinya: walaupun memiliki momen-momen cemerlang, dan dapat melakukan beberapa hal dengan cukup rapi, ada juga beberapa alasan yang sangat bagus bahwa itu (dan hampir pasti akan tetap) tidak jelas.
Sunting (delapan tahun kemudian, pada 2017): Beberapa pendahulunya telah menjadi usang setidaknya sampai tingkat tertentu. Sebagai contoh, Intel telah mengimplementasikan versi valarray yang dioptimalkan untuk kompilernya. Ini menggunakan Intel Integrated Performance Primitives (Intel IPP) untuk meningkatkan kinerja. Meskipun peningkatan kinerja yang tepat tidak diragukan lagi bervariasi, tes cepat dengan kode sederhana menunjukkan peningkatan kecepatan 2: 1, dibandingkan dengan kode identik yang dikompilasi dengan implementasi "standar"
valarray
.Jadi, sementara saya tidak sepenuhnya yakin bahwa programmer C ++ akan mulai menggunakan
valarray
dalam jumlah besar, setidaknya ada beberapa keadaan di mana ia dapat memberikan peningkatan kecepatan.sumber
Selama standarisasi C ++ 98, valarray dirancang untuk memungkinkan beberapa jenis perhitungan matematika cepat. Namun, sekitar waktu itu Todd Veldhuizen menemukan template ekspresi dan menciptakan blitz ++ , dan teknik template-meta serupa ditemukan, yang membuat valarrays cukup usang sebelum standar bahkan dirilis. IIRC, pengusul asli valarray meninggalkannya setengah jalan ke standardisasi, yang (jika benar) juga tidak membantunya.
ISTR bahwa alasan utama itu tidak dihapus dari standar adalah bahwa tidak ada yang meluangkan waktu untuk mengevaluasi masalah secara menyeluruh dan menulis proposal untuk menghapusnya.
Perlu diingat, bagaimanapun, bahwa semua ini hanya diingat secara samar-samar. Ambil ini dengan sebutir garam dan berharap seseorang memperbaiki atau mengkonfirmasi ini.
sumber
Saya harus mengatakan bahwa saya pikir tidak
std::valarrays
banyak mengandung gula sintaksis. Sintaksnya berbeda, tetapi saya tidak akan menyebut perbedaan itu "gula." APInya aneh. Bagian padastd::valarray
s di Bahasa Pemrograman C ++ menyebutkan API yang tidak biasa ini dan fakta bahwa, karenastd::valarray
s diharapkan sangat dioptimalkan, pesan kesalahan apa pun yang Anda dapatkan saat menggunakannya mungkin tidak akan intuitif.Karena penasaran, sekitar satu tahun yang lalu saya diadu
std::valarray
melawanstd::vector
. Saya tidak lagi memiliki kode atau hasil yang tepat (walaupun seharusnya tidak sulit untuk menulis sendiri). Menggunakan GCC saya memang mendapatkan sedikit manfaat kinerja ketika menggunakanstd::valarray
untuk matematika sederhana, tetapi tidak untuk implementasi saya untuk menghitung standar deviasi (dan, tentu saja, standar deviasi tidak begitu rumit, sejauh matematika berjalan).Saya menduga bahwa operasi pada setiap item dalam permainan besar( CATATAN , mengikuti saran dari musiphil , saya telah berhasil mendapatkan kinerja yang hampir sama daristd::vector
lebih baik dengan cache daripada operasi padastd::valarray
s.vector
danvalarray
).Pada akhirnya, saya memutuskan untuk menggunakan
std::vector
sambil memperhatikan hal-hal seperti alokasi memori dan pembuatan objek sementara.Keduanya
std::vector
danstd::valarray
menyimpan data dalam blok yang berdekatan. Namun, mereka mengakses data itu menggunakan pola yang berbeda, dan yang lebih penting, API untukstd::valarray
mendorong pola akses yang berbeda dari API untukstd::vector
.Sebagai contoh standar deviasi, pada langkah tertentu saya perlu menemukan rata-rata koleksi dan perbedaan antara nilai setiap elemen dan rata-rata.
Untuk itu
std::valarray
, saya melakukan sesuatu seperti:Saya mungkin lebih pintar dengan
std::slice
ataustd::gslice
. Sudah lebih dari lima tahun sekarang.Karena
std::vector
, saya melakukan sesuatu seperti:Hari ini saya pasti akan menulisnya secara berbeda. Jika tidak ada yang lain, saya akan mengambil keuntungan dari C ++ 11 lambdas.
Jelas bahwa kedua cuplikan kode ini melakukan hal yang berbeda. Sebagai
std::vector
contoh , contoh tidak membuat koleksi perantara sepertistd::valarray
contoh. Namun, saya pikir itu adil untuk membandingkan mereka karena perbedaan terkait dengan perbedaan antarastd::vector
danstd::valarray
.Ketika saya menulis jawaban ini, saya curiga bahwa mengurangi nilai elemen dari dua
std::valarray
s (baris terakhir dalamstd::valarray
contoh) akan lebih sedikit cache-friendly daripada baris yang sesuai dalamstd::vector
contoh (yang kebetulan juga menjadi baris terakhir).Ternyata, itu
Melakukan hal yang sama dengan
std::vector
contoh, dan memiliki kinerja yang hampir sama. Pada akhirnya, pertanyaannya adalah API mana yang Anda sukai.sumber
std::vector
akan bermain lebih baik dengan cache daripada astd::valarray
; mereka berdua mengalokasikan satu blok memori yang berdekatan untuk elemen-elemen mereka.valarray
contoh Anda di atas, Anda tidak harus membanguntemp
valarray
objek, tetapi Anda bisa saja selesaistd::valarray<double> differences_from_mean = original_values - mean;
, dan kemudian perilaku cache harus mirip denganvector
contoh tersebut. (Omong-omong, jikamean
benar-benarint
, tidakdouble
, Anda mungkin perlustatic_cast<double>(mean)
.)valarray
. Saya perlu melihat apakah itu meningkatkan kinerja. Adapunmean
menjadiint
: itu adalah kesalahan. Saya awalnya menulis contoh menggunakanint
s, dan kemudian menyadari bahwamean
kemudian akan sangat jauh dari rata-rata yang sebenarnya karena pemotongan. Tetapi saya melewatkan beberapa perubahan yang diperlukan pada putaran pengeditan pertama saya.valarray seharusnya membiarkan beberapa FORTRAN memproses vektor kebaikan pada C ++. Entah bagaimana dukungan kompiler yang diperlukan tidak pernah benar-benar terjadi.
Buku-buku Josuttis berisi beberapa komentar menarik (agak meremehkan) tentang valarray (di sini dan di sini ).
Namun, Intel sekarang tampaknya meninjau kembali valarray dalam rilis kompiler terbaru mereka (mis. Lihat slide 9 ); ini adalah perkembangan yang menarik mengingat bahwa set instruksi SIMD SSE 4-arah mereka akan segera diikuti oleh instruksi AVX 8-arah dan Larrabee 16-arah dan untuk kepentingan portabilitas, akan lebih baik untuk membuat kode dengan abstraksi seperti valarray dari (katakanlah) intrinsik.
sumber
Saya menemukan satu penggunaan yang baik untuk valarray. Ini untuk menggunakan valarray seperti array numpy.
Kita bisa menerapkan di atas dengan valarray.
Kami juga membutuhkan skrip python.
sumber
Standar C ++ 11 mengatakan:
Lihat C ++ 11 26.6.1-2.
sumber
Dengan
std::valarray
Anda dapat menggunakan notasi matematika standar seperti div1 = a*v2 + v3
luar kotak. Ini tidak dimungkinkan dengan vektor kecuali Anda menentukan operator Anda sendiri.sumber
std :: valarray ditujukan untuk tugas-tugas numerik yang berat, seperti Dinamika Cairan Komputasi atau Dinamika Struktur Komputasi, di mana Anda memiliki array dengan jutaan, terkadang puluhan juta item, dan Anda mengulanginya dalam satu lingkaran dengan jutaan catatan waktu. Mungkin hari ini std :: vector memiliki kinerja yang sebanding tetapi, sekitar 15 tahun yang lalu, valarray hampir wajib jika Anda ingin menulis pemecah angka yang efisien.
sumber