Apa itu coroutine? Bagaimana mereka terkait dengan konkurensi?
Apa itu coroutine? Bagaimana mereka terkait dengan konkurensi?
Jawaban:
Coroutine dan concurrency sebagian besar bersifat orthogonal. Coroutine adalah struktur kontrol umum di mana kontrol aliran secara kooperatif dilewatkan di antara dua rutinitas yang berbeda tanpa kembali.
Pernyataan 'hasil' dalam Python adalah contoh yang baik. Itu menciptakan coroutine. Ketika 'hasil' ditemui, keadaan fungsi saat ini disimpan dan kontrol dikembalikan ke fungsi pemanggilan. Fungsi panggilan kemudian dapat mentransfer eksekusi kembali ke fungsi menghasilkan dan statusnya akan dikembalikan ke titik di mana 'hasil' ditemukan dan eksekusi akan berlanjut.
Coroutines are a general control structure whereby flow control is cooperatively passed between two different routines without returning.
<- ini adalah konkurensi. Kata yang Anda cari adalah paralelisme.
orthogonal = Not similar to each other
?
orthogonal
berarti "tidak tergantung satu sama lain".
Dari Pemrograman di Lua , Coroutines
bagian " ":
Coroutine mirip dengan utas (dalam arti multithreading): itu adalah garis eksekusi, dengan tumpukan sendiri, variabel lokalnya sendiri, dan penunjuk instruksinya sendiri; tetapi berbagi variabel global dan sebagian besar hal lain dengan coroutine lain. Perbedaan utama antara utas dan coroutine adalah, secara konseptual (atau secara harfiah, dalam mesin multiprosesor), program dengan utas menjalankan beberapa utas secara paralel. Coroutine, di sisi lain, bersifat kolaboratif: pada waktu tertentu, sebuah program dengan coroutine hanya menjalankan salah satu dari coroutine-nya, dan coroutine yang berjalan ini menangguhkan pelaksanaannya hanya ketika secara eksplisit meminta untuk ditangguhkan.
Jadi intinya adalah: Coroutine adalah "kolaboratif". Bahkan dalam sistem multi-core, hanya ada satu coroutine yang berjalan pada waktu tertentu (tetapi beberapa thread dapat berjalan secara paralel). Ada non-preemptive antara coroutine, coroutine yang berjalan harus melepaskan eksekusi secara eksplisit.
Untuk " concurrency
", Anda dapat merujuk slide Rob Pike :
Concurrency adalah komposisi dari komputasi yang dieksekusi secara independen.
Jadi selama eksekusi coroutine A, ia melewati kontrol ke coroutine B. Kemudian setelah beberapa waktu, coroutine B melewati kontrol kembali ke coroutine A. Karena ada ketergantungan antara coroutine, dan mereka harus berjalan bersama-sama, sehingga dua coroutine tidak konkurensi .
Saya menemukan sebagian besar jawaban terlalu teknis walaupun itu adalah pertanyaan teknis. Saya mengalami kesulitan mencoba memahami proses coroutine. Saya agak mendapatkannya tetapi kemudian saya tidak mendapatkannya pada saat yang sama.
Saya menemukan jawaban ini di sini sangat membantu:
https://dev.to/thibmaek/explain-coroutines-like-im-five-2d9
Mengutip dari Idan Arye:
Untuk membangun cerita Anda, saya akan menuliskannya seperti ini:
Anda mulai menonton kartun, tetapi intro. Alih-alih menonton intro Anda beralih ke permainan dan memasuki lobi online - tetapi itu membutuhkan 3 pemain dan hanya Anda dan kakak Anda yang ada di dalamnya. Alih-alih menunggu pemain lain bergabung, Anda beralih ke pekerjaan rumah, dan jawab pertanyaan pertama. Pertanyaan kedua memiliki tautan ke video YouTube yang perlu Anda tonton. Anda membukanya - dan mulai memuat. Alih-alih menunggu untuk memuat, Anda beralih kembali ke kartun. Intro sudah berakhir, jadi Anda bisa menonton. Sekarang ada iklan - tetapi sementara pemain ketiga telah bergabung sehingga Anda beralih ke permainan Dan seterusnya ...
Idenya adalah Anda tidak hanya beralih tugas dengan sangat cepat agar terlihat seperti Anda melakukan semuanya sekaligus. Anda memanfaatkan waktu Anda menunggu sesuatu terjadi (IO) untuk melakukan hal-hal lain yang memang membutuhkan perhatian langsung Anda.
Pasti memeriksa tautannya, ada banyak lagi yang saya tidak bisa kutip semuanya.
Coroutine mirip dengan subrutin / utas. Perbedaannya adalah begitu pemanggil memanggil subrutin / utas, itu tidak akan pernah kembali ke fungsi pemanggil. Tetapi coroutine dapat kembali ke pemanggil setelah mengeksekusi beberapa kode yang memungkinkan pemanggil untuk mengeksekusi beberapa kode sendiri dan kembali ke titik coroutine di mana ia menghentikan eksekusi dan melanjutkan dari sana. yaitu. Coroutine memiliki lebih dari satu titik masuk dan keluar
Pada dasarnya, ada dua jenis Coroutine:
Kotlin mengimplementasikan coroutine stackless - itu artinya coroutine tidak memiliki stack sendiri, sehingga mereka tidak memetakan pada thread asli.
Ini adalah fungsi untuk memulai coroutine:
launch{}
async{}
Anda dapat belajar lebih banyak dari sini:
https://www.kotlindevelopment.com/deep-dive-coroutines/
https://blog.mindorks.com/what-are-coroutines-in-kotlin-bf4fecd476e9
Dari Python Coroutine :
Eksekusi coroutine Python dapat ditunda dan dilanjutkan di banyak titik (lihat coroutine). Di dalam tubuh fungsi coroutine, menunggu dan pengidentifikasi async menjadi kata kunci yang dipesan; menunggu ekspresi, async untuk dan async dengan hanya dapat digunakan dalam fungsi tubuh coroutine.
Dari Coroutines (C ++ 20)
Coroutine adalah fungsi yang dapat menunda eksekusi untuk dilanjutkan nanti . Coroutine tidak bertumpuk: mereka menunda eksekusi dengan kembali ke pemanggil. Hal ini memungkinkan untuk kode sekuensial yang dieksekusi secara asinkron (misalnya untuk menangani I / O non-blocking tanpa panggilan balik eksplisit), dan juga mendukung algoritma pada urutan tak terbatas yang dihitung malas dan penggunaan lainnya.
Bandingkan dengan jawaban orang lain:
Menurut pendapat saya, bagian yang dilanjutkan kemudian adalah perbedaan inti, seperti halnya @ Twinkle.
Meskipun banyak bidang dokumen masih dalam proses, bagian ini mirip dengan sebagian besar jawaban, kecuali @Nan Xiao.
Coroutine, di sisi lain, bersifat kolaboratif: pada waktu tertentu, sebuah program dengan coroutine hanya menjalankan salah satu dari coroutine-nya, dan coroutine yang berjalan ini menangguhkan pelaksanaannya hanya ketika secara eksplisit meminta untuk ditangguhkan.
Karena itu dikutip dari Program in Lua, mungkin itu terkait bahasa (tidak akrab dengan Lua saat ini), tidak semua dokumen menyebutkan hanya satu bagian.
Hubungannya dengan konkuren:
Ada bagian "Eksekusi" dari Coroutine (C ++ 20). Terlalu lama untuk mengutip di sini.
Selain detailnya, ada beberapa negara.
When a coroutine begins execution
When a coroutine reaches a suspension point
When a coroutine reaches the co_return statement
If the coroutine ends with an uncaught exception
When the coroutine state is destroyed either because it terminated via co_return or uncaught exception, or because it was destroyed via its handle
sebagai komentar dari @Adam Arold di bawah jawaban @ user217714. Ini konkurensi.
Tapi ini berbeda dari multithreading.
dari std :: thread
Utas memungkinkan beberapa fungsi untuk dieksekusi secara bersamaan. Utas memulai eksekusi segera setelah konstruksi objek utas terkait (sambil menunggu penundaan penjadwalan OS), mulai dari fungsi tingkat atas yang disediakan sebagai argumen konstruktor. Nilai kembalinya fungsi tingkat atas diabaikan dan jika itu berakhir dengan melemparkan pengecualian, std :: terminate disebut. Fungsi tingkat atas dapat mengkomunikasikan nilai kembali atau pengecualian ke pemanggil melalui std :: janji atau dengan memodifikasi variabel yang dibagi (yang mungkin memerlukan sinkronisasi, lihat std :: mutex dan std :: atomic)
Karena ini adalah konkurensi, ia berfungsi seperti multithreading terutama ketika menunggu tidak dapat dihindari (dari perspektif OS), itu juga mengapa membingungkan.
Coroutine adalah jenis khusus dari subprogram. Daripada hubungan master-slave antara penelepon dan subprogram yang disebut yang ada dengan subprogram konvensional, penelepon dan yang disebut coroutine lebih adil.
Coroutine adalah subprogram yang memiliki banyak entri dan mengendalikannya sendiri - didukung langsung di Lua
Juga disebut kontrol simetris: pemanggil dan yang disebut coroutine memiliki basis yang lebih setara
Panggilan coroutine dinamai resume
Resume pertama dari coroutine adalah untuk permulaan, tetapi panggilan berikutnya masuk pada titik tepat setelah pernyataan yang dieksekusi terakhir di coroutine
Coroutine berulang kali saling melanjutkan, mungkin selamanya
Coroutine menyediakan eksekusi kuasi-konkuren dari unit program (coroutine); eksekusi mereka disisipkan, tetapi tidak tumpang tindih
Saya menemukan penjelasan dari tautan ini cukup mudah. Tidak ada jawaban yang mencoba menjelaskan konkurensi vs paralelisme kecuali titik terakhir dalam jawaban ini .
dikutip dari "pemrograman Erlang", oleh Joe Armstrong, sang legendaris:
sebuah program bersamaan dapat berjalan secara potensial lebih cepat pada komputer paralel.
program bersamaan adalah program yang ditulis dalam bahasa pemrograman bersamaan. Kami menulis program bersamaan untuk alasan kinerja, skalabilitas, atau toleransi kesalahan.
bahasa pemrograman konkuren adalah bahasa yang memiliki konstruksi bahasa eksplisit untuk menulis program bersamaan. Konstruksi ini merupakan bagian integral dari bahasa pemrograman dan berperilaku dengan cara yang sama pada semua sistem operasi.
komputer paralel adalah komputer yang memiliki beberapa unit pemrosesan (CPU atau inti) yang dapat berjalan secara bersamaan.
Jadi konkurensi tidak sama dengan paralelisme. Anda masih dapat menulis program bersamaan pada komputer inti tunggal. Penjadwal pembagian waktu akan membuat Anda merasa program Anda berjalan secara bersamaan.
Program bersamaan memiliki potensi untuk berjalan secara paralel di komputer paralel tetapi tidak dijamin . OS hanya dapat memberi Anda satu inti untuk menjalankan program Anda.
Oleh karena itu, concurrency adalah model perangkat lunak dari program bersamaan yang tidak berarti program Anda dapat berjalan secara paralel secara fisik.
Kata "coroutine" terdiri dari dua kata: "co" (kooperatif) dan "rutinitas" (fungsi).
Sebuah. apakah itu mencapai konkurensi atau paralelisme?
Sederhananya, mari kita bahas pada komputer inti tunggal .
Concurrency dicapai dengan pembagian waktu dari OS. Utas menjalankan kode dalam kerangka waktu yang ditentukan pada inti CPU. Itu bisa didahului oleh OS. Ini juga dapat menghasilkan kontrol ke OS.
Coroutine, di sisi lain, menghasilkan kontrol ke coroutine lain di dalam utas, bukan ke OS. Jadi semua coroutine dalam utas masih mengeksploitasi kerangka waktu untuk utas itu tanpa menghasilkan inti CPU ke utas lain yang dikelola oleh OS.
Oleh karena itu, Anda dapat memikirkan coroutine yang mencapai pembagian waktu oleh pengguna bukan oleh OS (atau kuasi-paralelisme). Coroutine berjalan pada inti yang sama yang ditugaskan ke utas yang menjalankan coroutine tersebut.
Apakah Coroutine mencapai paralelisme? Jika itu adalah kode yang terikat CPU, tidak. Seperti pembagian waktu, itu membuat Anda merasa mereka berjalan secara paralel tetapi eksekusi mereka disisipkan tidak tumpang tindih. Jika terikat IO, ya, ia mencapai paralel dengan perangkat keras (perangkat IO) bukan oleh kode Anda.
b. bedanya dengan pemanggilan fungsi?
Seperti yang ditunjukkan gambar, tidak perlu menelepon return
untuk beralih kontrol. Itu bisa menghasilkan tanpa return
. Coroutine menyimpan dan membagikan status pada bingkai fungsi saat ini (tumpukan). Jadi ini jauh lebih ringan daripada fungsi karena Anda tidak perlu menyimpan register dan variabel lokal untuk ditumpuk dan mundur saat panggilan call ret
.
Saya akan memperluas jawaban @ user21714. Coroutine adalah jalur eksekusi independen yang tidak dapat berjalan secara bersamaan. Mereka bergantung pada pengontrol - misalnya python
perpustakaan pengontrol - untuk menangani peralihan di antara jalur ini. Tetapi agar ini bisa berhasil, coroutine sendiri perlu dipanggilyield
atau struktur serupa yang memungkinkan eksekusi mereka dijeda.
Threads sebaliknya berjalan pada sumber daya komputasi independen dan secara paralel satu sama lain. Karena mereka menggunakan sumber daya yang berbeda, maka tidak perlu meminta imbal hasil untuk memungkinkan jalan eksekusi lainnya berjalan.
Anda dapat melihat efek ini dengan memulai program multihreaded - misalnya jvm
aplikasi - di mana kedelapan core i7
core hyperthread Anda digunakan: Anda mungkin melihat utilisasi 797% pada Activity Monitor
atau Top
. Alih-alih saat menjalankan python
program biasa - bahkan program dengan coroutines
atau python threading
- pemanfaatannya akan maksimal 100%. Yaitu satu mesin hyperthread.