Saat ini saya sedang membuat bahasa pemrograman untuk bersenang-senang di mana idenya adalah bahwa setiap panggilan fungsi / blok baru (jika klausa, loop dll) akan bekerja di utas terpisah. Alih-alih membuat Thread baru, standarnya haruslah yang melakukan itu secara otomatis, dan jika Anda ingin menjalankannya di utas utama Anda harus menentukan itu.
Saya tidak tahu tentang multi-threaded, pemrograman paralel tapi saya tahu dasar-dasarnya (Futures, objek aman thread). Karena itu saya bertanya-tanya bagaimana bahasa seperti itu dapat terlihat sintaksis dan apakah mungkin untuk memulainya? Tujuannya bukan untuk membuatnya "berguna", itu lebih untuk bersenang-senang dan pengalaman belajar.
(Maaf jika ini adalah tempat yang salah untuk memposting. Jika demikian, saya akan dengan senang hati menghargai jika Anda mengarahkan saya ke tempat yang tepat di mana pertanyaan seperti milik saya diizinkan.)
Jawaban:
Baca lebih banyak tentang kelanjutan dan gaya kelanjutan-kelanjutan (dan kaitannya dengan utas atau coroutine) Saya sarankan untuk membaca SICP & Lisp In Small Pieces . Juga, Memprogram Bahasa Pragmatik memberikan ikhtisar yang berguna dari beberapa bahasa, dan akan membantu Anda untuk merancang bahasa Anda sendiri.
Sintaks tidak terlalu penting untuk mengeksplorasi ide . Semantik lebih penting. Saya menyarankan untuk mengadopsi beberapa S-expr seperti sintaks (sehingga Anda bisa membuat prototipe menggunakan Skema dan panggilannya / cc ) pada awalnya.
Setelah ide Anda lebih jelas (setelah beberapa percobaan), Anda dapat mendiskusikannya di lambda-the-ultimate , Anda dapat mendefinisikan sintaksis yang lebih seksi (yang sebenarnya penting jika Anda ingin orang mengadopsi bahasa Anda, dan yang juga penting adalah kualitasnya. implementasi, implementasi sampel perangkat lunak bebas, dokumentasi, perpustakaan standar, antarmuka fungsi asing, dll)
sumber
Anda mungkin tertarik membaca tentang penelitian Haskell terhadap data paralel . Jika Anda mencari-cari di youtube, Simon Peyton Jones telah memberikan beberapa pembicaraan menarik terkait dengan subjek juga.
Jika saya ingat benar dari pembicaraannya, dalam pemrograman fungsional murni, hampir sepele untuk menemukan peluang untuk membuat utas. Masalah utamanya dalam penelitiannya adalah memiliki terlalu banyak yang berumur pendek, sehingga overhead menciptakan benang dan mengkomunikasikan hasil mereka pada dasarnya lebih besar daripada manfaat paralelisme. Sebagai contoh, mudah untuk mengajarkan kompiler untuk memutar 100 utas untuk dikomputasi
sum $ fmap (+1) <100 length vector>
, tetapi apakah overhead membuatnya berharga?Triknya adalah mengkonsolidasikan utas ke dalam ukuran yang menguntungkan, tanpa membebani pemrogram untuk menunjukkannya secara manual. Ini masalah sulit yang perlu dipecahkan agar dapat secara efektif menggunakan PC masa depan dengan ribuan inti.
sumber
Inilah yang dilakukan Erlang. Ini menangani bergabung kembali dengan utas sebagian besar dengan menggunakan antrian. Ini adalah konsep yang brilian tetapi agak sulit untuk membungkus kepala Anda awalnya jika latar belakang Anda adalah bahasa jenis yang lebih prosedural. Saya sangat merekomendasikan melihatnya.
sumber
Pertama saya akan merekomendasikan Anda melihat PROMELA , bahasa yang digunakan untuk menggambarkan algoritma bersamaan sehingga pemeriksa model dapat memaksa semua eksekusi yang mungkin untuk memverifikasi itu tidak mampu melakukan perilaku yang salah. (Pemrograman bersamaan terkenal sulit untuk dilakukan dengan benar, itulah sebabnya teknik verifikasi seperti itu penting.) Ia tidak menjalankan semua konstruksi dalam utas yang terpisah, tetapi memang memiliki sintaks dan semantik yang agak aneh karena fokusnya adalah non determinisme dari program bersamaan.
Lebih abstrak, kalkulus π adalah pendekatan yang indah untuk memodelkan komputasi paralel. Sulit untuk membuat kepala Anda di sekitar kecuali Anda mendapatkan buku itu Communicating and Mobile Systems: The Pi Calculus , oleh Robin Milner. Ini membantu saya berpikir tentang komputasi paralel dalam arti yang lebih luas bahwa "banyak utas mengakses memori bersama". Sangat menarik bagaimana pernyataan bersyarat, "gotos" dan sebagainya dapat dibangun dari primitif paralel yang lebih sederhana dan alami.
Berkenaan dengan sintaks ... cara terbaik untuk menyelesaikannya adalah dengan menulis beberapa program sampel. Tulis program untuk mengurutkan array, atau secara bersamaan melakukan ping ke beberapa server dan melaporkan mana yang paling cepat direspon, atau mencoba memecahkan labirin secara paralel, atau yang lainnya. Saat Anda melakukan ini, hal-hal yang hilang dari sintaks Anda akan menjadi jelas, dan Anda dapat menambahkannya. Setelah Anda menambahkan beberapa hal, tanyakan pada diri Anda apakah mereka memiliki sesuatu yang sama, dan jika demikian mungkin Anda dapat menemukan pendekatan yang lebih sederhana yang dapat melayani berbagai tujuan.
sumber
Proyek serupa telah dicoba di masa lalu. Saya sarankan membaca klasik untuk menjarah ide. (Semua tautan menuju Wikipedia)
Unity Bahasa ini dulu / digunakan untuk mengajar pemrograman paralel. Saya tidak berpikir itu benar-benar dilaksanakan. Sintaksis agak samar, tetapi pada dasarnya Anda memiliki kumpulan pernyataan yang dieksekusi dalam urutan yang tidak diketahui dan berulang kali sampai tidak ada lagi yang bisa dilakukan. Ini paling dekat dengan apa yang Anda minta.
Occam Bahasa ini dirancang untuk benar-benar menggunakan tetapi tidak pernah benar-benar menarik perhatian. Di sini ada kata kunci PAR yang berarti bahwa daftar pernyataan harus dieksekusi secara paralel.
Erlang Bahasa lain di dunia nyata. Yang ini digunakan oleh perusahaan telekomunikasi Ericsson dan memiliki cukup banyak pengikut. Mereka telah bekerja keras untuk membuat paralelisme menjadi praktis dan bermanfaat.
Google GO Ini adalah favorit saya dari banyak orang. Secara konseptual sama dengan Erlang, tetapi dengan sintaksis yang lebih baik dan bobot Google di belakangnya. Apa yang salah bisa terjadi?
Saya ingin menutup dengan peringatan: Paralelisme sangat sulit untuk diperbaiki. Sebagian besar bug dalam program modern adalah hasil dari kesalahan . Anda yakin ingin ke sana?
sumber
Itu mungkin tetapi itu tidak akan berguna untuk 99+% dari semua aplikasi yang masuk akal. Logika adalah urutan-terikat urutan, ini adalah aliran. Langkah demi langkah Anda mencapai solusi untuk masalah dan urutan langkah-langkah itu penting, terutama karena output dari satu langkah akan menjadi input untuk langkah berikutnya.
Dalam beberapa kasus Anda memang memiliki banyak tugas yang dapat dilakukan secara independen satu sama lain, biasanya murah untuk mengaturnya secara berurutan sebelum membiarkannya berjalan secara paralel.
Jadi, saya pikir waktu Anda akan lebih baik dihabiskan untuk belajar bagaimana menggunakan fitur multi-threading dalam bahasa pemrograman favorit Anda.
sumber
Clojure mungkin layak dicoba untuk beberapa ide.
http://clojure-doc.org/articles/language/concurrency_and_parallelism.html
Berikut adalah beberapa pemikiran: Jika kita memanggil unit perhitungan yang dapat dilakukan secara mandiri tugas: 1. Tugas independen sehingga dapat dijalankan secara bersamaan 2. Tugas yang berbeda membutuhkan sumber daya yang berbeda dan mengambil waktu yang berbeda untuk menjalankan 3. Oleh karena itu tugas harus dijadwalkan untuk throughput maksimum 4. Satu-satunya program dalam posisi untuk bertindak sebagai penjadwal adalah sistem operasi
Hal-hal seperti pengiriman pusat apel besar adalah upaya untuk menyediakan penjadwal tersebut.
Di atas berarti bahwa tanggung jawab melaksanakan tugas tidak harus tanggung jawab dari bahasa pemrograman.
Pikiran kedua adalah mengurangi beban pemrograman sistem paralel sebanyak mungkin. Satu-satunya cara untuk melakukan ini adalah menghapus spesifikasi apa pun tentang bagaimana sesuatu harus dilakukan dari program. Suatu program seharusnya hanya menentukan apa yang harus dilakukan dan sisanya harus terjadi secara otomatis.
Di atas mungkin berarti bahwa bahasa dinamis dan kompilasi tepat waktu adalah cara untuk pergi.
sumber
Apa yang Anda cari disebut parallellism implisit, dan ada bahasa yang telah mengeksplorasi konsep ini, seperti Sun / Oracle's Fortress . Antara lain, itu (berpotensi) menjalankan loop paralel.
Sayangnya, itu sudah dihentikan dan ada banyak tautan mati di luar sana, tetapi Anda masih dapat menemukan beberapa PDF mengambang di sana, jika Anda google cukup keras:
https://www.eecis.udel.edu/~cavazos/cisc879-spring2008/papers/fortress.pdf (spesifikasi bahasa)
http://stephane.ducasse.free.fr/Teaching/CoursAnnecy/0506-Master/ForPresentations/Fortress-PLDITutorialSlides9Jun2006.pdf
http://www.oracle.com/technetwork/systems/ts-5206-159453.pdf
http://dl.acm.org/citation.cfm?id=1122972 (paywalled)
Yang perlu diperhatikan adalah bahwa Anda biasanya tidak ingin memulai utas aktual untuk setiap pernyataan / ungkapan, karena membuat dan memulai utas cenderung mahal - sebagai gantinya, Anda akan memiliki kumpulan utas tempat Anda memposting bit pekerjaan yang perlu dilakukan . Tapi itu detail implementasi.
sumber
Meskipun bukan bahasa pemrograman seperti itu, Anda harus melihat VHDL . Ini digunakan untuk menggambarkan sirkuit digital, yang secara alami melakukan semuanya secara paralel kecuali Anda secara khusus menyuruhnya melakukannya secara serial. Ini mungkin memberi Anda beberapa ide bagaimana merancang bahasa Anda dan jenis logika apa yang cocok untuk itu.
sumber
Ini dapat disimulasikan dengan cukup mudah di C ++. Pastikan saja bahwa "setiap" * panggilan fungsi diimplementasikan oleh a
std::future
. Menangani nilai balik hanya dilakukan dengan memanggil.get()
masa depan.Karenanya, Anda dapat membuat prototipe bahasa Anda dengan mengkompilasi ke C ++. Ini juga memberi tahu kita seperti apa sintaksisnya: perbedaan utama adalah bahwa Anda memisahkan titik panggilan (di mana argumen input disediakan) dari titik kembali (di mana fungsi output digunakan).
(*) Saya katakan "setiap fungsi" tetapi terserah Anda apa yang dianggap sebagai fungsi. Apakah
memset
intrinsik atau fungsi? Apakah penugasan bilangan bulat, atau penugasan tipe yang ditentukan pengguna adalah panggilan fungsi?sumber