กลไกของการบล็อกไปป์ไลน์และโครูทีนเพื่อค้นหาจำนวนเฉพาะ

Mechanism Go Pipeline Blocking



กลไกการปิดกั้นท่อ

  • กรณี:
intChan := make(chan int, 10) exitChan := make(chan bool, 1) go writeData(intChan) go readData(intChan, exitChan) for { _, ok := <-exitChan if !ok { break } }
  • คำถาม: ถ้าคุณออกจากระบบ go readData (intChan, exitChan) จะเกิดอะไรขึ้นกับโปรแกรม?
    • คำตอบ: หากคุณเพียงแค่เขียนข้อมูลลงในท่อ โดยไม่ต้องอ่าน , จะมีการปิดกั้นและการล็อคตายเหตุผลก็คือความจุของ intChan คือ 10 และรหัส writeData จะเขียนข้อมูล 50 ดังนั้นมันจะถูกบล็อกใน writeData ch<-i
  • ถ้าคอมไพลเลอร์ (รัน) พบว่าไพพ์มีเพียงการเขียน แต่ไม่มีการอ่านไพพ์จะถูกบล็อก
  • ความถี่ของท่อเขียนและท่ออ่านไม่สอดคล้องกันมันไม่สำคัญ

Coroutine สำหรับจำนวนเฉพาะ

  • ความต้องการ:
    • ในบรรดาตัวเลขที่ต้องใช้ในการนับ 1-80000 ซึ่งเป็นจำนวนเฉพาะ?
  • การวิเคราะห์ความคิด:
    • วิธีการแบบเดิมคือการใช้การวนซ้ำเพื่อพิจารณาว่าตัวเลขแต่ละตัวเป็นจำนวนเฉพาะหรือไม่
    • ใช้แนวทางพร้อมกัน / คู่ขนาน มอบหมายงานในการนับจำนวนเฉพาะให้กับหลาย (4) goroutines เพื่อให้เสร็จสมบูรณ์ , ใช้เวลาสั้น ๆ ในการทำงานให้เสร็จ.
  • แผนภาพการวิเคราะห์:

  • รหัส:
package main import ( 'fmt' ) //Put 1-8000 numbers into intChan func putNum(intChan chan int) { for i := 1 i <= 80000 i++ { intChan<- i } //Close intChan close(intChan) } // Take out the data from intChan and determine whether it is a prime number, if it is, then/put it into primeChan func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) { var flag bool // for { num, ok := <-intChan //intChan can't get it... if !ok { break } flag = true //assume it is a prime number // Determine if num is a prime number for i := 2 i < num i++ { if num% i == 0 {//Indicates that num is not a prime number flag = false break } } if flag { //Put this number into primeChan primeChan<- num } } fmt.Println('There is a primeNum coroutine because it cannot get data, exit') exitChan<- true } func main() { intChan := make(chan int , 1000) primeChan := make(chan int, 20000)//Put the result //Identify the exiting pipeline exitChan := make(chan bool, 4) //Open a coroutine and put 1-8000 numbers into intChan go putNum(intChan) //Open 4 coroutines, take out the data from intChan, and judge whether it is a prime number, if it is, put it in primeChan for i := 0 i < 4 i++ { go primeNum(intChan, primeChan, exitChan) } go func(){ for i := 0 i < 4 i++ { <-exitChan } //When we take out 4 results from exitChan, we can safely close primeChan close(primeChan) }() //Here the main thread, for processing //Traverse primeChan and take out the result for { res, ok := <-primeChan if !ok{ break } //Output the result fmt.Printf('prime number=%d ', res) } fmt.Println('main thread exits') }
  • สกัดกั้นผลการทำงานบางส่วน:



ทดสอบประสิทธิภาพของโครูทีนในการค้นหาจำนวนเฉพาะ

  • ใช้การทดสอบประสิทธิภาพโครูทีน:
func main() { intChan := make(chan int , 1000) primeChan := make(chan int, 20000)//Put the result //Identify the exiting pipeline exitChan := make(chan bool, 4) // 4 start := time.Now().Unix() //Open a coroutine and put 1-8000 numbers into intChan go putNum(intChan) //Open 4 coroutines, take out the data from intChan, and judge whether it is a prime number, if it is, put it in primeChan for i := 0 i <4 i++ { go primeNum(intChan, primeChan, exitChan) } //Here our main thread, for processing go func(){ for i := 0 i < 4 i++ { <-exitChan } end := time.Now().Unix() fmt.Println('Time-consuming to use coroutine=', end-start) //When we take out 4 results from exitChan, we can safely close primeChan close(primeChan) }() //Traverse our primeChan and take the result out for { _, ok := <-primeChan if !ok{ break } //Output the result //fmt.Printf('prime number=%d ', res) } fmt.Println('main thread exits') }
  • ผลลัพธ์ผลลัพธ์:



  • การทดสอบประสิทธิภาพวิธีการแบบดั้งเดิม:
package main import ( 'time' 'fmt' ) func main() { start := time.Now().Unix() for num := 1 num <= 80000 num++ { flag := true //assume it is prime // Determine if num is a prime number for i := 2 i < num i++ { if num% i == 0 {//Indicates that num is not a prime number flag = false break } } if flag { //Put this number into primeChan //primeChan<- num } } end := time.Now().Unix() fmt.Println('Ordinary method takes time=', end-start) }
  • ผลลัพธ์ผลลัพธ์