Middle
Workshopping nedir?
sobes.tech yapay zeka
AI'dan gelen yanıt
İş çalma (work stealing), çok iş parçacıklı sistemlerde yük dengeleme mekanizmasıdır; burada pasif çalışan bir işçi (worker), meşgul olan başka bir işçinin kuyruğundan görev çalar.
Ana özellikler:
- Merkezi olmayan: Her işçi kendi yerel görev kuyruğunu yönetir.
- Aktif: Pasif işçi, diğerlerinden aktif olarak iş arar.
- Yüksek performans: Dengesiz yüklerde etkilidir.
Golang'da, bu planlayıcıda (scheduler) goroutine'leri işletim sistemi iş parçacıklarına (M) dağıtmak için kullanılır. Bir M, mevcut işini (P üzerindeki goroutine paketleri) tamamladığında, diğer P'lerin yerel kuyruklarından goroutine'leri arar.
// Work stealing kavramını gösteren psödokod
package main
import "fmt"
import "sync"
import "time"
type Task struct {
id int
}
// Görev kuyruğu simülasyonu
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
}
// Başka bir kuyruktan "çalmak" için girişim
func (q *TaskQueue) StealTask() (Task, bool) {
q.mu.Lock()
defer q.mu.Unlock()
if len(q.tasks) < 2 { // Az görev varsa çalmıyoruz
return Task{}, false
}
// Ortadan veya sondan çalmak, yerel çekişle çakışmayı önlemek için
index := len(q.tasks) / 2
task := q.tasks[index]
q.tasks = append(q.tasks[:index], q.tasks[index+1:]...)
return task, true
}
// İşçi simülasyonu
func worker(id int, localQueue *TaskQueue, otherQueues []*TaskQueue, wg *sync.WaitGroup) {
defer wg.Done()
for {
// Yerel kuyruktan görev almaya çalışma
task, ok := localQueue.GetLocalTask()
if ok {
fmt.Printf("İşçi %d, görev %d'yi yerel olarak yapıyor\n", id, task.id)
time.Sleep(100 * time.Millisecond) // İşleme simülasyonu
continue
}
// Eğer yerel kuyruk boşsa, çalmak için dene
stolen := false
for _, queue := range otherQueues {
if queue == localQueue {
continue // Kendinden çalmıyoruz
}
task, ok := queue.StealTask()
if ok {
fmt.Printf("İşçi %d, görev %d'yi çaldı\n", id, task.id)
time.Sleep(100 * time.Millisecond) // İşleme simülasyonu
stolen = true
break // Başarılı çalmadan çık
}
}
if !stolen {
// Çalınacak görev kalmadıysa, pasif kalabilir veya durabilir
// Gerçek bir planlayıcıda daha karmaşık sonlandırma mekanizmaları olur
// Demo amaçlı, belli bir süre sonra çıkıyoruz
fmt.Printf("İşçi %d pasif durumda, bekliyor...\n", id)
time.Sleep(50 * time.Millisecond)
// Gerçek senaryoda burada sonlandırma veya park mekanizması olur
// return // Demo amaçlı çıkış izni veriyoruz
break // Basitleştirilmiş simülasyon
}
}
}
func main() {
numWorkers := 4
numTasks := 20
taskQueues := make([]*TaskQueue, numWorkers)
for i := range taskQueues {
taskQueues[i] = &TaskQueue{}
}
// Görevleri dengesiz dağıt, work stealing'i göstermek için
for i := 0; i < numTasks; i++ {
queueIndex := i % 2 // İlk iki işçiye daha fazla görev
taskQueues[queueIndex].AddTask(Task{id: i})
}
var wg sync.WaitGroup
for i := 0; i < numWorkers; i++ {
wg.Add(1)
// İşçinin "çalabilmesi" için tüm kuyruklara referanslar ver
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("Tüm görevler tamamlandı")
}
```}}}}}]}},{