求解多机调度问题 —— 贪心算法
- 问题分析
设有n个独立的作业{1, 2, …, n},由m台相同的机器{M1, M2, …, Mm}进行加工处理,作业i所需的处理时间为ti(1≤i≤n),每个作业均可在任何一台机器上加工处理,但不可间断、拆分。多机调度问题要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。 - 问题的解决方法
贪心算法求解多机调度问题的贪心策略是最长处理时间的作业优先,即把处理时间最长的作业分配给最先空闲的机器,这样可以保证处理时间长的作业优先处理,从而在整体上获得尽可能短的处理时间。
作业的个数为n,机器的数目为m
A: n<m
这种情况很简单,将n个作业分配给m个机器中的n个就可以了。
B: n>m
设7个独立作业{1, 2, 3, 4, 5, 6, 7}由3台机器{M1, M2, M3}加工处理,各作业所需的处理时间分别为{2, 14, 4, 16, 6, 5, 3}。这里给出三种解决办法:
(1)将作业平均分配给每个机器,所需的时间总共为22。
这样的算法思路简单,容易上手。但是没有考虑时间的节省问题,机器所运行的作业完全由作业的次序决定,当运行时间较长的作业集中在一起时,它们会被分配给同一个机器,效率较低。
如表1所示:
机器 | 作业 | 时间 |
---|---|---|
M1 | 1,2,3 | 2+14+4=20 |
M2 | 4,5 | 16+6=22 |
M3 | 6,7 | 5+3=8 |
(2)将作业按从小到大的顺序依次分配给空闲的机器。
时间为:2,7,23。
这种算法实现较为方便,同时也有考虑到时间的安排。但是运行时间最长的作业一定是最后完成的,如果运行最长作业前,其他机器运行时间相差无几,就会造成几个机器等待一个机器的状况,这样机器的运行效率比较低。
如表2所示:
机器 | 作业 | 时间 |
---|---|---|
M1 | 1,6 | 2+5+16=23 |
M2 | 7,5 | 3+6=9 |
M3 | 3,2 | 4+8=12 |
(3)通过对上面两种算法的思考,会想到把作业按从大到小的顺序一次分配给空闲的机器m 时,首先将 n 个作业依其所需的处理时间从大到小措序,然后依此顺序将作业分配给空闲的处理机,如图3所示。
按 贪心算法产生的作业调度如图。所需要的加工时间为17。
时间长为6, 11 ,15,17。这种算法很明显首先挑选了处理时间比较长的作业,这正是贪心算法的特点,总是做出在当前看来最好的选择,也就是说贪心算法并不从整体考虑,他所作出的选择只是在某种意义上局部最优的选择。
- 测试
-
结论
对于多机调度问题的求解,首先我们需要把作业按加工所用的时间从大到小排序;然后如果作业数目比机器的数目少或相等,则直接把作业分配下去;最后如果作业数目比机器的数目多,则每台机器上先分配一个作业,如下的作业分配时,是选那个表头上最小的链表加入新作业。 -
源代码
#include<stdio.h>
#define MAXLENGTH 10
int d[MAXLENGTH];
int S[MAXLENGTH][MAXLENGTH];
struct work{
int hour;
int number;
};
work t[MAXLENGTH];
void bubble_sort(work a[], int n){
int i, j;
work temp;
for (j = 0; j < n - 1; j++){
for ( i = 0; i < n-1-j; i++)
{
if (a[i].hour<a[i+1].hour)
{
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
}
}
void MultiMachine(work t[], int n, int d[], int m);
int main(){
int n;
int m;
int i;
printf("请输入待处理的作业个数:");
scanf("%d", &n);
printf("请输入作业需要处理的时间:");
for ( i = 0; i <n; i++)
{
scanf("%d", &t[i].hour);
t[i].number = i + 1;
}
bubble_sort(t, n);
printf("请输入机器的个数:");
scanf("%d", &m);
for ( i = 0; i < m; i++)
{
d[i] = 0;
}
MultiMachine(t, n, d, m);
getchar();
getchar();
getchar();
}
void MultiMachine(work t[], int n, int d[], int m){
int rear[MAXLENGTH];
int i, j, k;
for ( i = 0; i < m; i++)
{
S[i][0] = t[i].number;
rear[i] = 0;
d[i] = t[i].hour;
}
for ( i = m; i < n; i++)
{
for (j = 0, k = 1; k < m; k++){
if (d[k]<d[j])
{
j = k;
}
}
rear[j]++;
S[j][rear[j]] = t[i].number;
d[j] += t[i].hour;
}
for ( i = 0; i < m; i++)
{
printf("机器%d处理:", i + 1);
for ( j = 0; S[i][j]>0; j++)
{
printf("作业%d\t", S[i][j]);
}
printf("处理时间:%d\n",d[i]);
printf("\n");
}
}