Fitur apa yang dibutuhkan pengguna dari antarmuka MPI C ++?

28

Versi 3.0 dari standar MPI secara formal menghapus antarmuka C ++ (sebelumnya tidak digunakan lagi). Sementara implementasi mungkin masih mendukungnya, fitur-fitur yang baru di MPI-3 tidak memiliki antarmuka C ++ yang didefinisikan dalam standar MPI. Lihat http://blogs.cisco.com/performance/the-mpi-c-bindings-what-happened-and-why/ untuk informasi lebih lanjut.

Motivasi untuk menghapus antarmuka C ++ dari MPI adalah bahwa ia tidak memiliki nilai signifikan atas antarmuka C. Ada sedikit perbedaan selain "s / _ / :: / g" dan banyak fitur yang tidak biasa digunakan pengguna C ++ (misalnya penentuan tipe otomatis melalui templat).

Sebagai seseorang yang berpartisipasi dalam Forum MPI dan bekerja dengan sejumlah proyek C ++ yang telah mengimplementasikan antarmuka C ++ mereka sendiri ke fungsi MPI C, saya ingin tahu apa saja fitur yang diinginkan dari antarmuka C ++ ke MPI. Sementara saya berkomitmen untuk tidak melakukan apa pun, saya akan tertarik melihat implementasi antarmuka MPI C ++ mandiri yang memenuhi kebutuhan banyak pengguna.

Dan ya, saya kenal dengan Boost :: MPI ( http://www.boost.org/doc/libs/1_54_0/doc/html/mpi.html ) tetapi hanya mendukung fitur MPI-1 dan model serialisasi akan menjadi sangat sulit untuk mendukung RMA.

Satu antarmuka C ++ ke MPI yang saya sukai adalah Elemental ( https://github.com/poulson/Elemental/blob/master/src/core/imports/mpi.cpp ) jadi mungkin orang dapat menyediakan beberapa pro dan kontra yang pendekatan. Secara khusus, saya pikir MpiMap memecahkan masalah penting.

Jeff
sumber
Saya tidak berpikir bahwa ini adalah tempat yang tepat untuk pertanyaan seperti itu.
Jack Poulson
Bisakah Anda memberikan beberapa alasan untuk itu? Banyak pertanyaan MPI di situs ini menyarankan kepada saya bahwa orang-orang di sini siap untuk menjawab pertanyaan ini. Juga, 0,2 kenaikan suara per menit menunjukkan orang lain tidak setuju dengan penilaian Anda. Bagaimanapun, akan lebih bermanfaat untuk menyarankan tempat alternatif untuk memposting ini jika Anda tidak menyukai tempat saat ini.
Jeff
Pertanyaannya adalah pertanyaan yang berharga, dan saya pikir itu bisa mendapatkan beberapa tanggapan berharga pada milis ilmu komputasi yang lebih luas, jika ada dalam cakupan di sana. (Mungkin dicerna NA, SIAM-CSE, atau bahkan pos publik di G +?) Pertanyaan ini mungkin tidak cocok untuk situs Stack Exchange karena bersifat subyektif (lihat scicomp.stackexchange.com/help/dont-ask ) . Selama jawabannya konkret dan fokus pada kasus penggunaan khusus (tanpa pengulangan atau tumpang tindih yang signifikan), saya pikir ada baiknya tetap terbuka.
Geoff Oxberry
@ Jeff: Pertanyaan itu muncul seperti jajak pendapat bagi saya. Saya tidak membantah bahwa itu berharga, tetapi saya tidak melihat ada satu jawaban yang diterima. Akankah pertanyaan seperti itu menjadi tidak biasa untuk forum MPI?
Jack Poulson
@JackPoulson Saya tidak ingin tahu apa yang dianggap pelaksana adalah jawaban yang tepat; Saya ingin tahu apa yang dibutuhkan ilmuwan komputasi. Dalam hal ini, pertanyaannya memiliki jawaban yang objektif. Tidak ada satu jawaban yang benar tetapi itu tidak berarti itu adalah situasi subjektif.
Jeff

Jawaban:

17

Biarkan saya jawab dulu mengapa saya pikir antarmuka C ++ ke MPI pada umumnya tidak terlalu berhasil, setelah memikirkan masalah ini untuk waktu yang lama ketika mencoba memutuskan apakah kita harus menggunakan binding C standar MPI atau membangun sesuatu di level yang lebih tinggi :

Ketika Anda melihat kode MPI dunia nyata (katakanlah, PETSc, atau dalam kasus saya. II), orang menemukan bahwa mungkin secara mengejutkan, jumlah panggilan MPI sebenarnya tidak terlalu besar. Sebagai contoh, dalam garis 500k kesepakatan. II, hanya ada ~ 100 MPI panggilan. Konsekuensi dari ini adalah bahwa rasa sakit yang terlibat dalam menggunakan antarmuka tingkat rendah seperti ikatan MPI C, tidak terlalu besar. Sebaliknya, seseorang tidak akan mendapatkan banyak dengan menggunakan antarmuka tingkat yang lebih tinggi.

Pengamatan kedua saya adalah bahwa banyak sistem memiliki banyak pustaka MPI yang diinstal (implementasi MPI yang berbeda, atau versi yang berbeda). Ini menimbulkan kesulitan yang signifikan jika Anda ingin menggunakan, katakanlah, boost :: mpi yang tidak hanya terdiri dari file header: perlu ada beberapa instalasi dari paket ini juga, atau orang perlu membangunnya sebagai bagian dari proyek yang menggunakan boost :: mpi (tapi itu masalah tersendiri lagi, mengingat boost itu menggunakan sistem build sendiri, yang tidak seperti yang lain).

Jadi saya pikir semua ini telah bersekongkol melawan arus antarmuka C ++ ke MPI: Binding MPI C ++ yang lama tidak menawarkan keuntungan, dan paket eksternal mengalami kesulitan dengan dunia nyata.

Ini semua berkata, inilah yang saya pikir akan menjadi fitur pembunuh yang ingin saya miliki dari antarmuka tingkat yang lebih tinggi:

  • Itu harus generik. Harus menentukan tipe data variabel jelas tidak seperti C ++. Tentu saja, itu juga mengarah pada kesalahan. Kelas MpiMap Elemental sudah akan menjadi langkah pertama yang bagus (meskipun saya tidak tahu mengapa MpiMap::typevariabel tidak konst statis, sehingga dapat diakses tanpa membuat objek).

  • Seharusnya memiliki fasilitas untuk streaming tipe data yang berubah-ubah.

  • Operasi yang membutuhkan MPI_Op argumen (misalnya, reduksi) harus diintegrasikan dengan baik dengan std::functionantarmuka C ++ , sehingga mudah untuk hanya melewatkan pointer fungsi (atau lambda!) Daripada harus dengan cepat mendaftarkan sesuatu.

boost :: mpi sebenarnya memenuhi semua ini. Saya pikir jika itu hanya pustaka header, ini akan menjadi jauh lebih populer dalam praktiknya. Ini juga akan membantu jika mendukung fungsi-fungsi pasca-MPI 1.0, tetapi mari kita jujur: ini mencakup sebagian besar dari apa yang paling kita butuhkan.

Wolfgang Bangerth
sumber
Salah satu masalah dengan serialisasi di Boost :: MPI adalah bahwa itu tidak bekerja dengan satu sisi (alias RMA). Apakah Anda berpikir bahwa dimungkinkan untuk membuat tipe data MPI untuk objek C ++ yang diminati pengguna? Tentu saja, secara teori semua harus didukung tetapi saya lebih suka memulai dengan tujuan yang lebih pragmatis.
Jeff
Saya pikir itu adalah kesalahan untuk berpikir bahwa tipe data serial mungkin dapat bekerja dengan komunikasi satu sisi. Ini mengasumsikan pandangan bahwa serialisasi hanya melibatkan pengemasan data menjadi string dan di sisi lain membongkar lagi. Tetapi fungsi serialisasi dapat melakukan jauh lebih banyak (misalnya, melacak pointer ke objek lain, menghitung byte yang telah diserialisasi, dll) daripada yang bisa diharapkan untuk bekerja jika Anda tidak dapat menjalankan apa pun pada host tujuan. Pandangan saya adalah bahwa C ++ - gaya serialisasi dan komunikasi satu sisi hanyalah non-starter. Saya pikir tidak ada orang yang mengharapkan ini bekerja, jadi sedikit yang terlewatkan.
Wolfgang Bangerth
Hai Wolfgang, Anda benar bahwa MpiMap akan lebih elegan jika menggunakan variabel anggota statis. Saya telah mengatur ulang implementasinya: github.com/poulson/Elemental/commit/…
Jack Poulson
Ya, jauh lebih baik :-)
Wolfgang Bangerth
+1 tentang tidak banyak panggilan mpi di @WolfgangBangerth. Secara mendasar, mpi seharusnya membuat perhitungan lebih cepat, Anda ingin meminimalkan panggilan mpi karena harganya mahal!
Charles
6

Untuk memulai, ada dua kebutuhan saya:

  • Antarmuka harus dapat menghilangkan argumen yang berlebihan atau tidak perlu, misalnya MPI_IN_PLACE.
  • Antarmuka harus secara otomatis mendeteksi datatypes bawaan ala Elemental's MpiMap.
  • Jika / bila memungkinkan, tipe data yang ditentukan pengguna harus dibangun untuk kelas.
Jeff
sumber
5

Daftar saya tanpa urutan preferensi tertentu. Antarmuka harus:

  • hanya sundulan, tanpa ketergantungan apa pun kecuali <mpi.h> , dan pustaka standar,
  • menjadi generik dan dapat dikembangkan,
  • non-blocking hanya (jika Anda ingin memblokir, kemudian blok secara eksplisit, tidak secara default),
  • memungkinkan rangkaian operasi non-pemblokiran berbasis kelanjutan,
  • mendukung serialisasi yang dapat dikembangkan dan efisien (seperti Boost.Fusion, sehingga berfungsi dengan RMA),
  • memiliki penalti abstraksi nol (yaitu setidaknya secepat antarmuka C),
  • aman (penghancur masa depan yang tidak siap disebut? -> std :: terminate!),
  • memiliki DEBUGmode yang kuat dengan banyak pernyataan,
  • sangat type-safe (tidak ada ints / void * untuk semuanya, huh saya ingin tag menjadi tipe!),
  • itu harus bekerja dengan lambdas (mis. semua mengurangi + lambda),
  • gunakan pengecualian secara konsisten sebagai mekanisme pelaporan kesalahan dan penanganan kesalahan (tidak ada lagi kode kesalahan! tidak ada lagi argumen fungsi keluaran!),
  • MPI-IO harus menawarkan antarmuka I / O non-blocking dalam gaya Boost.AFIO,
  • dan ikuti saja praktik desain antarmuka C ++ modern yang bagus (tentukan tipe reguler, fungsi non-anggota non-anggota, bermain baik dengan semantik gerakan, operasi rentang dukungan, ...)

Ekstra:

  • izinkan saya untuk memilih pelaksana lingkungan MPI, yaitu kumpulan utas yang digunakan. Saat ini Anda dapat memiliki aplikasi dengan campuran OpenMP, MPI, CUDA, dan TBB ... semuanya pada saat yang sama, di mana setiap run-time berpikir itu memiliki lingkungan dan dengan demikian meminta sistem operasi untuk utas setiap kali mereka merasa seperti saya t. Serius?

  • gunakan konvensi penamaan STL (dan Boost). Mengapa? Setiap programmer C ++ mengetahuinya.

Saya ingin menulis kode seperti ini:

auto buffer = some_t{no_ranks};
auto future = gather(comm, root(comm), my_offsets, buffer)
              .then([&](){
                /* when the gather is finished, this lambda will 
                   execute at the root node, and perform an expensive operation
                   there asynchronously (compute data required for load 
                   redistribution) whose result is broadcasted to the rest 
                   of the communicator */
                return broadcast(comm, root(comm), buffer);
              }).then([&]() {
                /* when broadcast is finished, this lambda executes 
                   on all processes in the communicator, performing an expensive
                   operation asynchronously (redistribute the load, 
                   maybe using non-blocking point-to-point communication) */
                 return do_something_with(buffer);
              }).then([&](auto result) {
                 /* finally perform a reduction on the result to check
                    everything went fine */
                 return all_reduce(comm, root(comm), result, 
                                  [](auto acc, auto v) { return acc && v; }); 
              }).then([&](auto result) {
                  /* check the result at every process */
                  if (result) { return; /* we are done */ }
                  else {
                    root_only([](){ write_some_error_log(); });
                    throw some_exception;
                  }
              });

/* Here nothing has happened yet! */

/* ... lots and lots of unrelated code that can execute concurrently 
   and overlaps with communication ... */

/* When we now call future.get() we will block 
   on the whole chain (which might have finished by then!).
*/

future.get();

Pikirkan bagaimana seseorang dapat menghubungkan semua operasi ini menggunakan MPI_C's request. Anda harus menguji beberapa langkah perantara (atau setiap langkah tunggal) melalui banyak kode yang tidak terkait untuk melihat apakah Anda dapat memajukan rantai Anda tanpa memblokir .

gnzlbg
sumber
Ini adalah daftar persyaratan yang ketat. Beberapa dari mereka tidak mungkin untuk semua tujuan praktis (misalnya mendukung lambda dalam pengurangan). Namun, secara keseluruhan saya pikir itu adalah jenis hal yang harus didukung oleh komunitas MPI.
Jeff
Sedangkan untuk lingkungan utas dan runtime, MPI menggunakan baik utas maupun utas OS (POSIX, Windows atau Solaris, tergantung pada OS) secara internal. Saya tidak yakin saya mengerti persyaratan di sini.
Jeff
Masalahnya adalah MPI dapat secara acak meminta utas dari sistem operasi. Aplikasi saya memiliki kumpulan utas dan saya ingin MPI meminta utas-utas tersebut dari kumpulan utas saya. Ini saat ini tidak mungkin (dan biasanya bukan masalah), kecuali jika Anda memiliki aplikasi menggunakan OpenMP, TBB, dan MPI, masing-masing dengan kumpulan utas sendiri, masing-masing dengan jumlah inti 4x.
gnzlbg
1
MPI bisa tetapi secara umum tidak menggunakan utas OS secara internal. Dalam setiap kasus yang saya kenal (MPICH (2), MVAPICH2, OpenMPI, CrayMPI), hanya opsi runtime yang disediakan oleh pengguna yang menyebabkan hal ini terjadi, yaitu defaultnya adalah tidak. Blue Gene / Q MPI adalah pengecualian tetapi dalam bentuk yang tidak relevan dengan diskusi ini.
Jeff
Terima kasih @ Jeff! Bisakah Anda menguraikan bagaimana MPI menangani beberapa panggilan non-pemblokiran saat menggunakan utas tunggal? Apakah ini menggunakan coroutine / green threads / fiber?
gnzlbg
2

Secara pribadi, saya tidak keberatan memanggil fungsi gaya C panjang untuk alasan yang tepat yang disebutkan Wolfgang; benar-benar ada beberapa tempat Anda perlu memanggil mereka dan bahkan kemudian, mereka hampir selalu dibungkus oleh beberapa kode tingkat yang lebih tinggi.

Satu-satunya hal yang benar-benar mengganggu saya dengan MPI C-style adalah tipe data khusus dan, pada tingkat yang lebih rendah, operasi khusus (karena saya jarang menggunakannya). Sedangkan untuk tipe data khusus, saya akan mengatakan bahwa antarmuka C ++ yang baik harus dapat mendukung cara umum dan efisien dalam menangani ini, kemungkinan besar melalui serialisasi. Ini tentu saja rute yang boost.mpitelah ditempuh, yang jika Anda hati - hati , adalah penghemat waktu yang besar.

Adapun boost.mpimemiliki dependensi tambahan (terutama boost.serializationyang itu sendiri bukan header-saja), saya baru-baru ini menemukan perpustakaan serialisasi hanya C + + header yang disebut sereal yang tampaknya menjanjikan; diberikan itu membutuhkan compiler C ++ 11 compliant. Mungkin layak untuk dilihat dan digunakan sebagai dasar untuk sesuatu yang mirip boost.mpi.

GradGuy
sumber
Perhatikan bahwa saya tidak perlu mencari sesuatu untuk dimasukkan ke dalam standar MPI. Saya sepenuhnya setuju bahwa MPI harus hampir selalu "dililit oleh beberapa kode tingkat yang lebih tinggi", jadi apa yang saya pikirkan adalah, seperti apa kode tingkat yang lebih tinggi itu? Elemental memiliki pendekatan yang bagus, tetapi apakah itu yang terbaik untuk semua kasus? Jika seseorang ingin memiliki antarmuka C ++ ke MPI yang mencoba membuat banyak orang bahagia, seperti apa tampilannya?
Jeff
@ Jeff. Bagi saya: 1. Saya ingin dapat mengirim tipe data khusus dengan mudah. 2. Saya ingin dapat melakukan pengurangan dengan operasi kustom dengan mudah. Juga saya pikir 1 saya bergoyang lebih penting / berguna daripada 2
GradGuy
Saya tidak melihat bagaimana C ++ melakukan sesuatu yang ajaib (2). Apa yang kamu bayangkan di sini?
Jeff
@ Jeff, saya memikirkan sesuatu thrustuntuk mengurangi: docs.thrust.googlecode.com/hg/group__reductions.html
GradGuy
-1

Proyek github easyLambda menyediakan antarmuka tingkat tinggi ke MPI dengan C ++ 14.

Saya pikir proyek ini memiliki tujuan yang sama dan akan memberikan beberapa gagasan tentang hal-hal yang dapat dan sedang dilakukan di bidang ini dengan menggunakan C ++ modern. Membimbing upaya lain serta easyLambda sendiri.

Tolok ukur awal pada kinerja dan garis kode telah menunjukkan hasil yang menjanjikan.

masukkan deskripsi gambar di sini

Berikut ini adalah deskripsi singkat fitur dan antarmuka yang disediakannya.

Antarmuka didasarkan pada pemrograman aliran data dan operasi daftar fungsional yang menyediakan paralelisme yang melekat. Paralelisme diekspresikan sebagai properti dari suatu tugas. Alokasi proses dan distribusi data untuk tugas dapat diminta dengan properti .prll (). Ada sejumlah contoh yang baik di halaman web dan repositori-kode yang meliputi LAMMPS dinamika molekul pasca pemrosesan, solusi beda hingga eksplisit untuk persamaan panas, regresi logistik dll. Sebagai contoh masalah difusi panas yang dibahas dalam artikel HPC sedang sekarat ... dapat diekspresikan dalam ~ 20 baris kode.

Saya harap tidak masalah untuk memberikan tautan daripada menambahkan rincian dan contoh kode di sini.

Disclamer: Saya adalah penulis perpustakaan. Saya percaya saya tidak melakukan kesalahan dengan berharap mendapatkan umpan balik yang konstruktif pada antarmuka easyLambda saat ini yang mungkin bermanfaat bagi easyLambda dan proyek lain yang mengejar tujuan yang sama.

Utkarsh Bhardwaj
sumber
Pertanyaan itu mengatakan, " Kami mencari jawaban panjang yang memberikan penjelasan dan konteks. Jangan hanya memberikan jawaban satu baris; jelaskan mengapa jawaban Anda benar, idealnya dengan kutipan. Jawaban yang tidak termasuk penjelasan dapat dihapus . " Menurut Anda mengapa jawaban Anda cukup lengkap agar sesuai dengan deskripsi ini?
nicoguaro
Saya menunjuk ke proyek yang menyediakan antarmuka yang mirip dengan apa yang diminta OP. Saya dapat memberikan rincian motivasi dan fitur proyek dalam jawaban itu sendiri dan membiarkan OP dan yang lain membaca dan menyarankan apa yang mereka pikirkan tentang itu. Namun, saya memilih untuk memberikan tautan saja. Saya mengerti maksud Anda. Biarkan saya menambahkan beberapa teks dengan referensi ke jawabannya.
Utkarsh Bhardwaj
@UtkarshBhardwaj: Beberapa komentar: (1) Terima kasih telah menulis perpustakaan yang menghubungkan C ++ dengan MPI. Ini adalah usaha yang signifikan dan sepertinya Anda telah melakukan banyak pekerjaan. (2) Dengan cepat membaca dokumen (sekali lagi, pekerjaan yang bagus), yang menonjol adalah rantai panjang perintah metode yang digunakan, yang tampaknya bergaya ... menyakitkan untuk di-debug, meskipun Anda telah memformatnya dengan baik. (3) Abstraksi mengandaikan paradigma fungsional, yang terlihat berguna untuk tugas-tugas seperti pengurangan peta, tetapi sebagai seseorang yang memprogram dalam MPI, saya tidak ingin mengerjakan ulang algoritme saya dan terlalu banyak pindah dari antarmuka yang saya tahu.
Geoff Oxberry
(4) Saya tidak melihat komunikator di manapun dalam contoh ini, yang membuat saya curiga Anda menggunakan MPI_COMM_WORLD untuk semuanya, dan membatasi potensi perpustakaan Anda. (5) Abstraksi-abstraksi tersebut tampaknya dibangun di atas abstraksi-abstraksi MPI dan dapat memiliki backend yang berbeda. (6) Berdasarkan pada (3) - (5), saya tidak berpikir perpustakaan ini adalah antarmuka MPI, dan saya percaya komentar ini di luar topik sebagai hasilnya.
Geoff Oxberry
@ Geoff terima kasih atas umpan balik yang berharga, sangat menghargai. Membalas poin tertentu: 2) Rantai ini kadang-kadang disebut sebagai ExpressionBuilder . Ini adalah cara umum untuk mengekspresikan komposisi dalam gaya fungsional. Tidak perlu menulis dengan gaya ini di ezl. Dimungkinkan untuk menulis unit individu terlebih dahulu & kemudian menyusunnya, periksa [contoh] ( goo.gl/YzaL0k ). 3) Saya tahu sulit untuk beralih dari kontrol-aliran & imperatif ke aliran data & fungsional. Masing-masing sudah ada pro & kontra. Namun, saya percaya yang terakhir perlu lebih dieksplorasi untuk mengetahui kemanjurannya yang sebenarnya.
Utkarsh Bhardwaj