B424 Parallel and Distributed Programming

6. Operating Systems Simulations

Some programs inspired from tasks that could be a part of an operating system.

6.1 Pool of Tasks

Fig. 6.1 Pool of tasks

Method Features

General Algorithm

for each worker
  while (true) {
   
get a task from the pool;
   
if (no more tasks)
    
 break;
   
execute task, possibly generating new ones;
 
}

The simple model

The master generates one task at a time and assigns it to the first available worker.

The workers wait for a task and execute it while they are not told to stop.

Master() 
{
 
do {
   
task = Generate_task();
   
if (task != done) {
     
Recv(worker, any_process);
     
Send(task, worker);
   
}
 
} while (task != done);
 
Finish_all();
}

Finish_all() 
{
 
for(i=1, i<=nb_workers; i++) { // nb_workers = nb_proc-1
   
Recv(worker, any_process);
   
Send(done, worker);
 
}
}

Worker() 
{
 
do {
 
   Send(proc_id, master);
   
Recv(task, master);
   
if (task != done)
     
Execute_task(task);
 
} while (task != done);

Example: Chess

A second model with a queue of tasks

Master() 
{
 
Queue q;
 
while (tasks not finished) {
   
choose randomly between     Generate_store_task(q);
     
Assign_task(q);
 
}
 
while (!q.is_empty())
   
Assign_task(q);
 
Finish_all();
}

Generate_store_task(q) 
{
 
task = Generate_task();
 
q.enqueue(task);
}


Assign_task(q)
{
 
Recv(result, any_process);
 
worker = which; // status.MPI_Source
 
if (q.is_empty())
   
Generate_store_task(q);
 
task = q.dequeue();
 
Send(task, worker);
}

Worker() 
{
 
result = none;
 
do {
  
 Send(result, master);
   
Recv(task, master);
   
if (task != done)
     
result = Execute_task(task);
 
} while (task != done);
}

The complete model

Fig 6.2 Pool of tasks, complete model

Master() 
{
 
Queue task_q, worker_q;
 
while (tasks not finished) {
   
choose randomly between    Generate_store_task(task_q); Get_free_worker(task_q, worker_q);
     
Assign_task(task_q, worker_q);
 
}
 
while (!task_q.is_empty()) {
   
choose randomly between
     
Assign_task(q);
    
Get_free_worker(task_q, worker_q);
 
} while (worker_q.size() != nb_proc-1)
    Get_free_worker(task_q, worker_q);
 
Finish_all();
}

Assign_task(task_q, worker_q)
{
 
if (!task_q.is_empty() and !worker_q.is_empty()) {
   
task = task_q.dequeue();
   
worker = worker_q.dequeue();
   
Send(task, worker);
 
}
}

Get_free_worker(task_q, worker_q) 
{
 
Recv(task, any_process);
 
worker = which; // status.MPI_Source
 
worker_q.enqueue(worker);
 
if (To_be_assigned(task))
   
task_q.enqueue(task);
}

Note. The implementation of this model can be a project.