Middle
Workshopping nima?
sobes.tech AI
AIdan javob
Work stealing (ishdan olish) — bu ko‘p ipli tizimlarda yukni muvozanatlash mexanizmi bo‘lib, bu yerda passiv ishchi (worker) band bo‘lmagan oqimdan (thread) vazifalarni "o‘g‘irlaydi".
Asosiy xususiyatlar:
- Markazlashmagan: Har bir oqim o‘zining lokal vazifa navbatini boshqaradi.
- Faol: Passiv oqim faol ravishda boshqalardan ish qidiradi.
- Yuqori samaradorlik: Noto‘g‘ri yuklangan vazifalar uchun samarali.
Golangda, bu schedulerda (rejalashtiruvchi) goroutinlarni operatsion tizim oqimlariga (M) taqsimlash uchun ishlatiladi. Bir M o‘zining hozirgi ishini (P ustidagi goroutinlar paketini) tugatgach, u boshqa Plarning lokal navbatlaridan goroutinlarni qidiradi.
// Work stealing konseptini ko‘rsatadigan pseudokod
package main
import "fmt"
import "sync"
import "time"
type Task struct {
id int
}
// Vazifa navbatini simulyatsiya qilish
type TaskQueue struct {
tasks []Task
mu sync.Mutex
}
func (q *TaskQueue) AddTask(task Task) {
q.mu.Lock()
defer q.mu.Unlock()
q.tasks = append(q.tasks, task)
}
func (q *TaskQueue) GetLocalTask() (Task, bool) {
q.mu.Lock()
defer q.mu.Unlock()
if len(q.tasks) == 0 {
return Task{}, false
}
task := q.tasks[0]
q.tasks = q.tasks[1:]
return task, true
}
// Boshqa navbatdan "o‘g‘irlangan" vazifa
func (q *TaskQueue) StealTask() (Task, bool) {
q.mu.Lock()
defer q.mu.Unlock()
if len(q.tasks) < 2 { // Kam vazifa bo‘lsa, o‘g‘irlashmaydi
return Task{}, false
}
// O‘g‘irlash o‘rtadan yoki oxiridan, lokal chiqarish bilan to‘qnashuvni oldini olish uchun
index := len(q.tasks) / 2
task := q.tasks[index]
q.tasks = append(q.tasks[:index], q.tasks[index+1:]...)
return task, true
}
// Ishchi funksiyasi
func worker(id int, localQueue *TaskQueue, otherQueues []*TaskQueue, wg *sync.WaitGroup) {
defer wg.Done()
for {
// Lokal navbatdan vazifa olishga harakat qilamiz
task, ok := localQueue.GetLocalTask()
if ok {
fmt.Printf("Worker %d, vazifa %d ni lokal ravishda bajaradi\n", id, task.id)
time.Sleep(100 * time.Millisecond) // Ishlashni simulyatsiya qilish
continue
}
// Agar lokal navbat bo‘sh bo‘lsa, o‘g‘irlashga harakat qilamiz
stolen := false
for _, queue := range otherQueues {
if queue == localQueue {
continue // O‘zimdan o‘g‘irlash
}
task, ok := queue.StealTask()
if ok {
fmt.Printf("Worker %d vazifa %d ni o‘g‘irldi\n", id, task.id)
time.Sleep(100 * time.Millisecond) // Ishlashni simulyatsiya qilish
stolen = true
break // Muvaffaqiyatli o‘g‘irlanganidan keyin chiqish
}
}
if !stolen {
// Agar o‘g‘irlash muvaffaqiyatsiz bo‘lsa, ehtimol vazifa qolmagan
// Haqiqiy schedulerda, murakkabroq yakunlash mexanizmlari bo‘ladi
// Demo uchun, kutish bilan chiqamiz
fmt.Printf("Worker %d passiv, kutmoqda...\n", id)
time.Sleep(50 * time.Millisecond)
// Haqiqiy scenarioda, bu yerda yakunlash yoki parking mexanizmi bo‘ladi
// return // Demo uchun, chiqishga ruxsat beramiz
break // Simulyatsiyani soddalashtirish uchun
}
}
}
func main() {
numWorkers := 4
numTasks := 20
taskQueues := make([]*TaskQueue, numWorkers)
for i := range taskQueues {
taskQueues[i] = &TaskQueue{}
}
// Vazifalarni notekis taqsimlash, work stealingni ko‘rsatish uchun
for i := 0; i < numTasks; i++ {
queueIndex := i % 2 // Birinchi ikki ishchiga ko‘proq vazifa
taskQueues[queueIndex].AddTask(Task{id: i})
}
var wg sync.WaitGroup
for i := 0; i < numWorkers; i++ {
wg.Add(1)
// Har bir navbatga referenslarni uzatamiz, shunda ishchi "o‘g‘irishi" mumkin
otherQueues := make([]*TaskQueue, 0, numWorkers-1)
for j := range taskQueues {
if i != j {
otherQueues = append(otherQueues, taskQueues[j])
}
}
go worker(i, taskQueues[i], otherQueues, &wg)
}
wg.Wait()
fmt.Println("Barcha vazifalar bajarildi")
}
```}}}}}]}]}}}]},