程式排程之最短作業優先

tb_youth發表於2020-11-21

程式排程之最短作業優先

最短作業優先

SJF(Shortest-Job-First):

  • 分為搶佔式和非搶佔式:
    • 非搶佔式的SJF 更確切的叫 最短下次CPU執行演算法(shortest-next-CPU-burst)
    • 佔式的SJF 叫 最短剩餘時間優先演算法(shortest-remaining-time-first)
  • 優點:
    它的平均等待時間最小,是最優的排程演算法。
  • 缺點:
    獲取下次CPU執行長度比較困難(一般估計)。
  • 用途:
    經常用於長期排程

程式碼

根據個人思路模擬的FCFS,僅供參考

非搶佔式

#include <iostream>
#include <queue>

using namespace std;
typedef  double TimeType;
const int MAXN =  1e6+5;

int task_num;
TimeType now_time; //從第一個到達的作業時間開始
TimeType avg_spend_time; //平均週轉時間
TimeType avg_weight_time; //平均帶權週轉時間

struct StruTask
{
    int id; //序號
    TimeType arrive_time; //到達時間(輸入)
    TimeType service_time; //服務時間(輸入)
    TimeType start_time; //開始時間(設定)
    TimeType end_time; //結束時間(設定)
    TimeType spend_time; //週轉時間:end_time - arrive_time
    TimeType weight_time; //帶權週轉時間spend_time/service_time
    bool finished;

} arrayTask[MAXN];



TimeType get_task()
{
    cout<<"請輸入任務數:"<<endl;
    cin>>task_num;
    if(task_num <= 0) return -1;
    cout<<"----------請輸入任務相關資訊-------"<<endl;
    TimeType minx = 1e15;
    for(int i = 1; i <= task_num; ++i)
    {
        cout<<"請輸入第"<<i<<"個任務的 到達時間 和 服務時間:";
        arrayTask[i].id = i;
        cin>>arrayTask[i].arrive_time;
        minx = min(minx,arrayTask[i].arrive_time);
        cin>>arrayTask[i].service_time;
    }
    return minx;
}

int get_next_task()
{
    int minx = 1<<30;
    int aim = 0;
    for(int i = 1; i <= task_num; ++i)
    {
        if(arrayTask[i].arrive_time<=now_time && !arrayTask[i].finished)
        {
            if(arrayTask[i].service_time < minx)
            {
                minx = arrayTask[i].service_time;
                aim = i;
            }
        }
    }
    return aim;

}


void run_task(StruTask &task)
{
    now_time = max(now_time,task.arrive_time);
    task.start_time  = now_time;
    task.end_time = now_time + task.service_time;
    now_time = task.end_time;
    task.spend_time = task.end_time - task.arrive_time;
    avg_spend_time += task.spend_time;
    task.weight_time = task.spend_time / task.service_time;
    avg_weight_time += task.weight_time;
    task.finished = true;
}

void print_result(StruTask &task)
{
    cout<<" id: "<<task.id
        <<" arrive_time: "<<task.arrive_time<<" service: "<<task.service_time;
    cout<<" start: "<<task.start_time<<" end: "<<task.end_time;
    cout<<" spend: "<<task.spend_time<<" weight: "<<task.weight_time<<endl;
}

/*SJF 非搶佔式
Short Job First
*/
void SJF()
{

    avg_spend_time = 0;
    avg_weight_time = 0;
    for(int i = 1; i <= task_num; ++i)
    {
        int id = get_next_task();
        run_task(arrayTask[id]);
        print_result(arrayTask[id]);
    }
}


int main()
{
    now_time = get_task();
    if(now_time == -1)
        return 0;
    SJF();
    double wait = 0;
    for(int i = 1; i <= task_num; ++i)
    {
        wait += arrayTask[i].start_time - arrayTask[i].arrive_time;
    }
    avg_spend_time /= task_num;
    avg_weight_time /= task_num;
    cout<<" avg_spend: "<<avg_spend_time<<" avg_weight: "<<avg_weight_time<<endl;
    cout<<" avg_wait: "<<(wait/task_num)<<endl;
    return 0;
}

執行示例

4
0 6
0 8
0 7
0 3

在這裡插入圖片描述

4
0 8
1 4
3 5
2 9

在這裡插入圖片描述

搶佔式

#include <iostream>
#include <queue>
using namespace std;
typedef  double TimeType;
const int MAXN =  1e3+5;

int task_num;
TimeType now_time; //從第一個到達的作業時間開始
TimeType avg_spend_time; //平均週轉時間
TimeType avg_weight_time; //平均帶權週轉時間
TimeType avg_wait;
TimeType last_run[MAXN];

struct StruTask
{
    int id; //序號
    TimeType arrive_time; //到達時間(輸入)
    TimeType service_time; //服務時間(輸入)
    TimeType start_time; //開始時間(設定)
    TimeType end_time; //結束時間(設定)
    TimeType spend_time; //週轉時間:end_time - arrive_time
    TimeType weight_time; //帶權週轉時間spend_time/service_time
    TimeType remain_service_time; //剩餘服務時間

} arrayTask[MAXN];

TimeType get_task()
{
    cout<<"請輸入任務數:"<<endl;
    cin>>task_num;
    if(task_num <= 0) return -1;
    cout<<"----------請輸入任務相關資訊-------"<<endl;
    TimeType minx = 1e15;
    for(int i = 1; i <= task_num; ++i)
    {
        cout<<"請輸入第"<<i<<"個任務的 到達時間 和 服務時間:";
        arrayTask[i].id = i;
        cin>>arrayTask[i].arrive_time;
        minx = min(minx,arrayTask[i].arrive_time);
        cin>>arrayTask[i].service_time;
        arrayTask[i].remain_service_time = arrayTask[i].service_time;
    }
    return minx;
}

int get_next_task()
{
    TimeType minx = 1e15;
    int aim = -1;
    for(int i = 1; i <= task_num; ++i)
    {
        if(arrayTask[i].arrive_time<=now_time && arrayTask[i].remain_service_time)
        {
            if(arrayTask[i].remain_service_time < minx)
            {
                minx = arrayTask[i].remain_service_time;
                aim = i;
            }
        }
    }
    return aim;

}


void run_task(StruTask &task)
{
    now_time = max(now_time,task.arrive_time);
    avg_wait += now_time - (last_run[task.id]==-1?task.arrive_time:last_run[task.id]);

    task.start_time  = now_time;
    task.end_time = now_time + 1; // 執行一秒後詢問,便於實現
    task.remain_service_time -= 1;
    now_time = task.end_time;
    last_run[task.id] = now_time;
    if(!task.remain_service_time)
    {
        task.spend_time = task.end_time - task.arrive_time;
        avg_spend_time += task.spend_time;
        task.weight_time = task.spend_time / task.service_time;
        avg_weight_time += task.weight_time;
    }

}

void print_result(StruTask &task)
{
    cout<<" id: "<<task.id
        <<" arrive_time: "<<task.arrive_time<<" service: "<<task.service_time;
    cout<<" start: "<<task.start_time<<" end: "<<task.end_time;
    cout<<" spend: "<<task.spend_time<<" weight: "<<task.weight_time<<endl;
}

/*SJF 搶佔式:又叫最短剩餘時間優先
Shortest remaining time first
*/
void SRTF()
{

    avg_spend_time = 0;
    avg_weight_time = 0;
    avg_wait = 0;
    for(int i = 0; i < MAXN; ++i)
    {
        last_run[i] = -1;
    }
    int id;
    while(1)
    {
        id = get_next_task();
        if(id == -1) break;
        run_task(arrayTask[id]);
        print_result(arrayTask[id]);
    }
}


int main()
{
    now_time = get_task();
    if(now_time == -1)
        return 0;
    SRTF();
    avg_spend_time /= task_num;
    avg_weight_time /= task_num;
    avg_wait /= task_num;
    cout<<" avg_spend: "<<avg_spend_time<<" avg_weight: "<<avg_weight_time<<endl;
    cout<<" avg_wait: "<<avg_wait<<endl;
    return 0;
}

執行示例

4
0 8
2 9
3 5
1 4

在這裡插入圖片描述

相關文章