Analisis mendalam tentang sebab mengapa terdapat model penjadualan GMP dalam bahasa Go

青灯夜游
Lepaskan: 2023-04-14 15:26:34
ke hadapan
1848 orang telah melayarinya

Mengapa Go mempunyai model penjadualan GMP? Artikel berikut akan memperkenalkan kepada anda sebab mengapa terdapat model penjadualan GMP dalam bahasa Go. Saya harap ia akan membantu anda!

Analisis mendalam tentang sebab mengapa terdapat model penjadualan GMP dalam bahasa Go

Model penjadualan GMP ialah intipati Go. Ia secara munasabah menyelesaikan masalah kecekapan coroutine penjadualan serentak berbilang benang.

Apakah itu GMP

Pertama sekali, kita mesti faham apa yang dimaksudkan oleh setiap generasi GMP.

  • G: Singkatan Goroutine, yang merujuk kepada coroutine dan berjalan pada benang.
  • M: Singkatan Mesin, iaitu tead, benang, coroutine penjadualan kitaran dan pelaksanaan.
  • P: Singkatan bagi Processor, merujuk kepada pemproses, yang menyimpan coroutine dalam baris gilir tempatan dan menyediakan coroutine yang tersedia yang tidak aktif untuk thread

Thread M setiap satu ditahan Apabila a pemproses P ingin mendapatkan coroutine, ia pertama kali diperoleh daripada P, jadi gambar rajah model GMP adalah seperti berikut:

Analisis mendalam tentang sebab mengapa terdapat model penjadualan GMP dalam bahasa Go

Proses umum ialah benang M memperolehnya daripada P baris gilir Jika coroutine tidak dapat memperolehnya, ia akan bersaing untuk mendapatkan kunci daripada baris gilir global untuk mendapatkannya.

Pemproses P

Struktur coroutine G dan benang M telah diterangkan dalam artikel sebelumnya Di sini kami menganalisis pemproses P.

Fungsi

Pemproses P menyimpan sekumpulan coroutine, supaya thread M boleh mendapatkan coroutine daripada mereka tanpa mengunci, tanpa perlu bersaing dengan thread lain untuk baris gilir global Coroutine dalam proses, dengan itu meningkatkan kecekapan penjadualan coroutine.

Analisis kod sumber

Kod sumber struktur p berada dalam srcruntimeruntime2.go dan beberapa medan penting ditunjukkan di sini.

type p struct {
   ...
   m           muintptr   // back-link to associated m (nil if idle)
   // Queue of runnable goroutines. Accessed without lock.
   runqhead uint32
   runqtail uint32
   runq     [256]guintptr
   runnext guintptr
   ...
}
Salin selepas log masuk
  • m ialah urutan yang dimiliki oleh pemproses p
  • runq ialah baris gilir
  • runqhead yang menyimpan. coroutines. runqtailMewakili penunjuk kepala dan ekor barisan
  • runnextmenunjuk ke coroutine boleh lari seterusnya

Analisis mendalam tentang sebab mengapa terdapat model penjadualan GMP dalam bahasa Go

Thread M dan Bagaimanakah pemproses P bekerjasama?

Dalam srcruntimeproc.go, terdapat kaedah schedule, iaitu fungsi pertama yang dijalankan oleh benang. Dalam fungsi ini, utas perlu mendapatkan coroutine boleh laku Kodnya adalah seperti berikut:

func schedule() {    
    ...
    // 寻找一个可运行的协程
    gp, inheritTime, tryWakeP := findRunnable() 
    ...
}
Salin selepas log masuk
func findRunnable() (gp *g, inheritTime, tryWakeP bool) {
    // 从本地队列中获取协程
    if gp, inheritTime := runqget(pp); gp != nil {
       return gp, inheritTime, false
    }

    // 本地队列拿不到则从全局队列中获取协程
    if sched.runqsize != 0 {
       lock(&sched.lock)
       gp := globrunqget(pp, 0)
       unlock(&sched.lock)
       if gp != nil {
          return gp, false, false
       }
    }
}
Salin selepas log masuk

Dapatkan coroutine daripada baris gilir tempatan

func runqget(pp *p) (gp *g, inheritTime bool) {
   next := pp.runnext // 队列中下一个可运行的协程
   if next != 0 && pp.runnext.cas(next, 0) {
      return next.ptr(), true
   }
   ...
}
Salin selepas log masuk

Kemudian jika baris gilir tempatan dan Apakah yang perlu saya lakukan jika tiada coroutine dalam baris gilir global Patutkah kita membiarkan sahaja urutan terbiar?

Pada masa ini, pemproses P akan mencuri tugasan dan mencuri beberapa tugasan daripada baris gilir setempat bagi utas lain Ini dipanggil berkongsi tekanan utas lain dan meningkatkan penggunaan utasnya sendiri.

Kod sumber ada dalam srcruntimeproc.gostealWork, anda boleh lihat jika anda berminat.

Di manakah coroutine yang baru dibuat harus diperuntukkan?

Adakah coroutine yang baru dibuat perlu diperuntukkan kepada baris gilir tempatan atau global Markah:

  • Go berpendapat bahawa coroutine baharu mempunyai keutamaan yang tinggi, jadi ia mula-mula mencari baris gilir tempatan untuk memasukkannya ke dalam Enter dan melompat dalam barisan.
  • Apabila barisan pasukan ini penuh, ia akan dimasukkan ke dalam barisan global.

Proses sebenar ialah:

  1. Cari P secara rawak
  2. Masukkan coroutine baharu ke dalam P runnext, yang bermaksud yang seterusnya akan dijalankan Coroutine ini melompat ke dalam baris gilir
  3. Jika coroutine P penuh, ia dimasukkan ke dalam baris gilir global

Kod sumber berada dalam fungsi srcruntimeproc.gonewproc.

// Create a new g running fn.
// Put it on the queue of g's waiting to run.
// The compiler turns a go statement into a call to this.
func newproc(fn *funcval) {
   gp := getg()
   pc := getcallerpc()
   systemstack(func() {
      newg := newproc1(fn, gp, pc) // 创建新协程

      pp := getg().m.p.ptr()
      runqput(pp, newg, true) // 寻找本地队列放入

      if mainStarted {
         wakep()
      }
   })
}
Salin selepas log masuk

Kesimpulan

Artikel ini pada mulanya memperkenalkan model penjadualan GMP dan memperincikan cara pemproses P dan benang M memperoleh coroutine.

Pemproses P menyelesaikan masalah pengecualian bersama berbilang benang untuk mendapatkan coroutine dan meningkatkan kecekapan penjadualan coroutine Walau bagaimanapun, tidak kira sama ada coroutine berada dalam baris gilir tempatan atau global, nampaknya ia hanya dilaksanakan secara berurutan. Jadi bagaimana dengan Go? Bagaimana untuk melaksanakan pelaksanaan coroutine tak segerak dan serentak? Mari kita sambung analisis dalam artikel seterusnya (walaupun tiada siapa yang akan membacanya...).

Pembelajaran yang disyorkan: Tutorial Golang

Atas ialah kandungan terperinci Analisis mendalam tentang sebab mengapa terdapat model penjadualan GMP dalam bahasa Go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!