V-3.0 Single Priority Array O(1) CPU Scheduler Evaluation
PATCH 1/1 V-3.0 Single Priority Array O(1) CPU Scheduler Evaluation
Version 3 of the various single priority array scheduler patches for 2.6.7, 2.6.8-rc2 and 2.6.8-rc2-mm1 kernels are now available for download and evaluation:
1. Standard O(1) scheduler with active/expired arrays replaced by a single array and an O(1) promotion mechanism plus scheduling statistics:
2.6.7 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.7-spa_trad_FULL-v3.0?download>
2.6.8-rc2 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2-spa_trad_FULL-v3.0.1?download>
2.6.8-rc2-mm1 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2_mm1-spa_trad_FULL-v3.0?download>
2. Basic O(1) scheduler with active/expired arrays replaced by a single array and an O(1) promotion mechanism plus scheduling statistics with all interactive bonus etc. removed:
2.6.7 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.7-spa_base_FULL-v3.0?download>
2.6.8-rc2 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2-spa_base_FULL-v3.0.1?download>
2.6.8-rc2-mm1 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2_mm1-spa_base_FULL-v3.0?download>
3. Priority based O(1) scheduler with active/expired arrays replaced by a single array and an O(1) promotion mechanism plus scheduling statistics with new interactive bonus mechanism and throughput bonus mechanism:
2.6.7 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.7-spa_pb_FULL-v3.0?download>
2.6.8-rc2 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2-spa_pb_FULL-v3.0.1?download>
2.6.8-rc2-mm1 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2_mm1-spa_pb_FULL-v3.0?download>
4. Runtime selectable choice between a priority based or entitlement based O(1) scheduler with active/expired arrays replaced by a single array and an O(1) promotion mechanism plus scheduling statistics with new interactive bonus mechanism and throughput bonus mechanism:
2.6.7 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.7-spa_zaphod_FULL-v3.0?download>
2.6.8-rc2 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2-spa_zaphod_FULL-v3.0.1?download>
2.6.8-rc2-mm1 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2_mm1-spa_zaphod_FULL-v3.0?download>
5. Slightly modified version of Con Kolivas's staircase O(1) scheduler with active/expired arrays replaced by a single array and an O(1) promotion mechanism:
2.6.7 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.7-spa_sc_FULL-v3.0?download>
2.6.8-rc2 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2-spa_sc_FULL-v3.0.1?download>
2.6.8-rc2-mm1 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2_mm1-spa_sc_FULL-v3.0?download>
6. Runtime selection between staircase, priority based and entitlement based O(1) schedulers:
2.6.7 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.7-spa_hydra_FULL-v3.0?download>
2.6.8-rc2 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2-spa_hydra_FULL-v3.0.1?download>
2.6.8-rc2-mm1 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2_mm1-spa_hydra_FULL-v3.0?download>
7. Standard O(1) scheduler with scheduling statistics added:
2.6.7 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.7-stats-v3.0?download>
2.6.8-rc2 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2-stats-v3.0.1?download>
2.6.8-rc2-mm1 <http://prdownloads.sourceforge.net/cpuse/patch-2.6.8-rc2_mm1-stats-v3.0?download>
Peter
Signature · 4 lines
Peter Williams [email protected] "Learning, n. The kind of ignorance distinguishing the studious." -- Ambrose Bierce
Quoted 4 lines · Peter Williams
3. Priority based O(1) scheduler with active/expired arrays replaced by a single array and an O(1) promotion mechanism plus scheduling statistics with new interactive bonus mechanism and throughput bonus mechanism:
Hmm. Given do_promotions() I'd expect fenceposts, not iteration over the priority levels of the runqueue.
-- wli
Quoted 7 lines · William Lee Irwin III
Quoted 1 line · Peter Williams
3. Priority based O(1) scheduler with active/expired arrays replaced by a single array and an O(1) promotion mechanism plus scheduling statistics with new interactive bonus mechanism and throughput bonus mechanism:
Hmm. Given
do_promotions()I'd expect fenceposts, not iteration over the priority levels of the runqueue.
I don't understand what you mean. Do you mean something like the more complex promotion mechanism in the (earlier) EBS scheduler where tasks only get promoted if they've been on a queue without being serviced within a given time?
Peter
Signature · 4 lines
Peter Williams [email protected] "Learning, n. The kind of ignorance distinguishing the studious." -- Ambrose Bierce
Quoted 2 lines · William Lee Irwin III
Quoted 2 lines
Hmm. Given
do_promotions()I'd expect fenceposts, not iteration over the priority levels of the runqueue.
Quoted 4 lines · Peter Williams
I don't understand what you mean. Do you mean something like the more complex promotion mechanism in the (earlier) EBS scheduler where tasks only get promoted if they've been on a queue without being serviced within a given time?
An array of size N can be rotated in O(1) time if an integer is kept along with it to represent an offset that has to be added to externally- visible indices mod N to recover the true index.
-- wli
Quoted 6 lines · William Lee Irwin III
Quoted 2 lines · William Lee Irwin III
Quoted 2 lines
Hmm. Given
do_promotions()I'd expect fenceposts, not iteration over the priority levels of the runqueue.
Quoted 6 lines
Quoted 1 line · Peter Williams
I don't understand what you mean. Do you mean something like the more complex promotion mechanism in the (earlier) EBS scheduler where tasks only get promoted if they've been on a queue without being serviced within a given time?
An array of size N can be rotated in O(1) time
And with a smaller constant than my do_promotions(). :-)
Quoted 3 lines
if an integer is kept
along with it to represent an offset that has to be added to externally- visible indices mod N to recover the true index.
OK. Now I understand.
The main reason that I didn't do something like that is that (considering that real time tasks don't get promoted) it would complicate:
1. the selection (in schedule()) of the next task to be run as it would no longer be a case of just finding the first bit in the bitmap,
2. determining the appropriate list to put the task on in enqueue_task(), etc., and
3. determining the right bit to turn off in the bit map when dequeuing the last task in a slot.
As these are frequent operations compared to promotion I thought it would be better to leave the complexity in do_promotion(). Now that you've caused me to think about it again I realize that the changes in the above areas may not be as complicated as I thought would be necessary. So I'll give it some more thought.
Thanks for the suggestion
Peter
Signature · 4 lines
Peter Williams [email protected] "Learning, n. The kind of ignorance distinguishing the studious." -- Ambrose Bierce
Quoted 6 lines · Peter Williams
OK. Now I understand.
The main reason that I didn't do something like that is that (considering that real time tasks don't get promoted) it would complicate:
1. the selection (inschedule()) of the next task to be run as it would no longer be a case of just finding the first bit in the bitmap,
2. determining the appropriate list to put the task on in
Quoted 8 lines
enqueue_task(), etc., and
3. determining the right bit to turn off in the bit map when dequeuing the last task in a slot.
As these are frequent operations compared to promotion I thought it would be better to leave the complexity indo_promotion(). Now that you've caused me to think about it again I realize that the changes in the above areas may not be as complicated as I thought would be necessary. So I'll give it some more thought.
In such schemes, realtime tasks are considered separately from timesharing tasks. Finding a task to run or migrate proceeds with a circular search of the portion of the bitmap used for timesharing tasks after a linear search of that for RT tasks. The list to enqueue a timesharing task in is just an offset from the fencepost determined by priority. Dequeueing is supported with a tag for actual array position. I did this for aperiodic queue rotations, which differs from your SPA.
-- wli
Quoted 10 lines · William Lee Irwin III
Quoted 6 lines · Peter Williams
OK. Now I understand.
The main reason that I didn't do something like that is that (considering that real time tasks don't get promoted) it would complicate:
1. the selection (inschedule()) of the next task to be run as it would no longer be a case of just finding the first bit in the bitmap,
2. determining the appropriate list to put the task on inenqueue_task(), etc., and
3. determining the right bit to turn off in the bit map when dequeuing the last task in a slot.
As these are frequent operations compared to promotion I thought it would be better to leave the complexity indo_promotion(). Now that you've caused me to think about it again I realize that the changes in the above areas may not be as complicated as I thought would be necessary. So I'll give it some more thought.
Quoted 7 lines
In such schemes, realtime tasks are considered separately from timesharing tasks. Finding a task to run or migrate proceeds with a circular search of the portion of the bitmap used for timesharing tasks after a linear search of that for RT tasks. The list to enqueue a timesharing task in is just an offset from the fencepost determined by priority. Dequeueing is supported with a tag for actual array position. I did this for aperiodic queue rotations, which differs from your SPA.
While pondering this I have stumbled on a problem that rules out using a rotating list for implementing promotion. The problem is that one of the requirements is that once a SCHED_NORMAL task is promoted to the MAX_RT_PRIO slot it stays there (as far as promotion is concerned). With the rotating list this isn't guaranteed and, in fact, any tasks that are in the MAX_RT_PRIO slot when promotion occurs will actually be demoted to IDLE_PRIO - 1.
Promotion should be a rare event as it is unnecessary if there's less than two tasks on the runqueue and when there are more than one task on the runqueue the interval between promotions increases linearly with the number of runnable tasks. It is also an O(1) operation albeit with a constant factor determined by the number of occupied SCHED_NORMAL priority slots.
I will modify the code to take better advantage of the fact that promotion is not required when the number of runnable tasks is less than 2 e.g. by resetting next_prom_due so that the first promotion after the number of runnable tasks exceeds 1 will only occur after a full promotion interval has expired. At normal loads (and with sensible promotion interval settings i.e. greater than the time slice size) this should result in promotion never (or hardly ever) occurring and the overhead of do_promotions() will only have to be endured when it's absolutely necessary.
Peter
Signature · 4 lines
Peter Williams [email protected] "Learning, n. The kind of ignorance distinguishing the studious." -- Ambrose Bierce
Quoted 7 lines · William Lee Irwin III
Quoted 7 lines
In such schemes, realtime tasks are considered separately from timesharing tasks. Finding a task to run or migrate proceeds with a circular search of the portion of the bitmap used for timesharing tasks after a linear search of that for RT tasks. The list to enqueue a timesharing task in is just an offset from the fencepost determined by priority. Dequeueing is supported with a tag for actual array position. I did this for aperiodic queue rotations, which differs from your SPA.
Quoted 7 lines · Peter Williams
While pondering this I have stumbled on a problem that rules out using a rotating list for implementing promotion. The problem is that one of the requirements is that once a
SCHED_NORMALtask is promoted to theMAX_RT_PRIOslot it stays there (as far as promotion is concerned). With the rotating list this isn't guaranteed and, in fact, any tasks that are in theMAX_RT_PRIOslot when promotion occurs will actually be demoted toIDLE_PRIO- 1.
Aperiodic rotations defer movement until MAX_RT_PRIO's slot is evacuated.
Quoted 6 lines · Peter Williams
Promotion should be a rare event as it is unnecessary if there's less than two tasks on the runqueue and when there are more than one task on the runqueue the interval between promotions increases linearly with the number of runnable tasks. It is also an O(1) operation albeit with a constant factor determined by the number of occupied
SCHED_NORMALpriority slots.
The asymptotics were in terms of SCHED_NORMAL priorities.
Quoted 9 lines · Peter Williams
I will modify the code to take better advantage of the fact that promotion is not required when the number of runnable tasks is less than 2 e.g. by resetting
next_prom_dueso that the first promotion after the number of runnable tasks exceeds 1 will only occur after a full promotion interval has expired. At normal loads (and with sensible promotion interval settings i.e. greater than the time slice size) this should result in promotion never (or hardly ever) occurring and the overhead ofdo_promotions()will only have to be endured when it's absolutely necessary.
The primary concern was that ticklessness etc. may require it to occur during context switches.
-- wli
Quoted 11 lines · William Lee Irwin III
Quoted 7 lines · William Lee Irwin III
Quoted 7 lines
In such schemes, realtime tasks are considered separately from timesharing tasks. Finding a task to run or migrate proceeds with a circular search of the portion of the bitmap used for timesharing tasks after a linear search of that for RT tasks. The list to enqueue a timesharing task in is just an offset from the fencepost determined by priority. Dequeueing is supported with a tag for actual array position. I did this for aperiodic queue rotations, which differs from your SPA.
Quoted 6 lines
Quoted 1 line · Peter Williams
While pondering this I have stumbled on a problem that rules out using a rotating list for implementing promotion. The problem is that one of the requirements is that once a
SCHED_NORMALtask is promoted to theMAX_RT_PRIOslot it stays there (as far as promotion is concerned). With the rotating list this isn't guaranteed and, in fact, any tasks that are in theMAX_RT_PRIOslot when promotion occurs will actually be demoted toIDLE_PRIO- 1.Aperiodic rotations defer movement until MAX_RT_PRIO's slot is evacuated.
Unfortunately, to ensure no starvation, promotion has to continue even when there are tasks in MAX_RT_PRIO's slot.
Quoted 10 lines · Peter Williams
Quoted 2 lines
Promotion should be a rare event as it is unnecessary if there's less than two tasks on the runqueue and when there are more than one task on the runqueue the interval between promotions increases linearly with the number of runnable tasks. It is also an O(1) operation albeit with a constant factor determined by the number of occupied
SCHED_NORMALpriority slots.The asymptotics were in terms of
SCHED_NORMALpriorities.
Quoted 7 lines
Quoted 1 line · Peter Williams
I will modify the code to take better advantage of the fact that promotion is not required when the number of runnable tasks is less than 2 e.g. by resetting
next_prom_dueso that the first promotion after the number of runnable tasks exceeds 1 will only occur after a full promotion interval has expired. At normal loads (and with sensible promotion interval settings i.e. greater than the time slice size) this should result in promotion never (or hardly ever) occurring and the overhead ofdo_promotions()will only have to be endured when it's absolutely necessary.The primary concern was that ticklessness etc. may require it to occur during context switches.
On a tickless system, I'd consider using a timer to control when do_promotions() gets called. I imagine something similar will be necessary to manage time slices?
Peter
Signature · 4 lines
Peter Williams [email protected] "Learning, n. The kind of ignorance distinguishing the studious." -- Ambrose Bierce
Quoted 1 line · William Lee Irwin III
Quoted 1 line
Aperiodic rotations defer movement until MAX_RT_PRIO's slot is evacuated.
Quoted 2 lines · Peter Williams
Unfortunately, to ensure no starvation, promotion has to continue even when there are tasks in MAX_RT_PRIO's slot.
One may either demote to evict MAX_RT_PRIO immediately prior to rotation or rely on timeslice expiry to evict MAX_RT_PRIO. Forcibly evicting MAX_RT_PRIO undesirably accumulates tasks at the fencepost.
Quoted 2 lines · William Lee Irwin III
Quoted 2 lines
The primary concern was that ticklessness etc. may require it to occur during context switches.
Quoted 3 lines · Peter Williams
On a tickless system, I'd consider using a timer to control when
do_promotions()gets called. I imagine something similar will be necessary to manage time slices?
This is an alternative to scheduler accounting in context switches. Periodicity often loses power conservation benefits.
-- wli
Quoted 5 lines · William Lee Irwin III
Quoted 1 line · William Lee Irwin III
Quoted 1 line
Aperiodic rotations defer movement until MAX_RT_PRIO's slot is evacuated.
Quoted 8 lines
Quoted 1 line · Peter Williams
Unfortunately, to ensure no starvation, promotion has to continue even when there are tasks in MAX_RT_PRIO's slot.
One may either demote to evict
MAX_RT_PRIOimmediately prior to rotation or rely on timeslice expiry to evictMAX_RT_PRIO. Forcibly evictingMAX_RT_PRIOundesirably accumulates tasks at the fencepost.
It's starting to get almost as complex as the current scheme :-)
Quoted 8 lines
Quoted 2 lines · William Lee Irwin III
Quoted 2 lines
The primary concern was that ticklessness etc. may require it to occur during context switches.
Quoted 7 lines
Quoted 1 line · Peter Williams
On a tickless system, I'd consider using a timer to control when
do_promotions()gets called. I imagine something similar will be necessary to manage time slices?This is an alternative to scheduler accounting in context switches. Periodicity often loses power conservation benefits.
The timer would be deactivated whenever the number of runnable tasks for the runqueue goes below 2. The whole thing could be managed from the enqueue and dequeue functions i.e.
dequeue - if the number running is now less than two cancel the timer and otherwise decrease the expiry time to maintain the linear relationship of the interval with the number of runnable tasks
enqueue - if the number of runnable tasks is now 2 then start the time with a single interval setting and if the number is greater than two then increase the timer interval to maintain the linear relationship.
I'm assuming here that add_timer(), del_timer() and (especially) mod_timer() are relatively cheap. If mod_timer() is too expensive some alternative method could be devised to maintain the linear relationship.
Peter
Signature · 4 lines
Peter Williams [email protected] "Learning, n. The kind of ignorance distinguishing the studious." -- Ambrose Bierce
Quoted 8 lines · Peter Williams
Quoted 6 lines
Quoted 2 lines
Unfortunately, to ensure no starvation, promotion has to continue even when there are tasks in MAX_RT_PRIO's slot.
One may either demote to evict
MAX_RT_PRIOimmediately prior to rotation or rely on timeslice expiry to evictMAX_RT_PRIO. Forcibly evictingMAX_RT_PRIOundesirably accumulates tasks at the fencepost.It's starting to get almost as complex as the current scheme :-)
hey, it's 'complex' for a reason ;)
Ingo
Quoted 3 lines · William Lee Irwin III
Quoted 3 lines
One may either demote to evict
MAX_RT_PRIOimmediately prior to rotation or rely on timeslice expiry to evictMAX_RT_PRIO. Forcibly evictingMAX_RT_PRIOundesirably accumulates tasks at the fencepost.
Quoted 1 line · Peter Williams
It's starting to get almost as complex as the current scheme :-)
Compare it to the background scan of the queue if several (potentially numerous) events whose handling has been deferred are to be processed when timer device interrupts are delivered at irregular intervals, or not at all.
Quoted 2 lines · William Lee Irwin III
Quoted 2 lines
This is an alternative to scheduler accounting in context switches. Periodicity often loses power conservation benefits.
Quoted 4 lines · Peter Williams
The timer would be deactivated whenever the number of runnable tasks for the runqueue goes below 2. The whole thing could be managed from the enqueue and dequeue functions i.e.
dequeue - if the number running is now less than two cancel the timer
Quoted 8 lines
and otherwise decrease the expiry time to maintain the linear relationship of the interval with the number of runnable tasks enqueue - if the number of runnable tasks is now 2 then start the time with a single interval setting and if the number is greater than two then increase the timer interval to maintain the linear relationship. I'm assuming here that
add_timer(),del_timer()and (especially)mod_timer()are relatively cheap. Ifmod_timer()is too expensive some alternative method could be devised to maintain the linear relationship.
Naive schemes reprogram the timer device too frequently. Software constructs are less of a concern. This also presumes that taking timer interrupts when cpu-intensive workloads voluntarily yield often enough is necessary or desirable. This is not so in virtualized environments, and unnecessary interruption of userspace also degrades performance.
-- wli
Quoted 10 lines · William Lee Irwin III
William Lee Irwin III wrote:
Quoted 4 lines · Peter Williams
The timer would be deactivated whenever the number of runnable tasks for the runqueue goes below 2. The whole thing could be managed from the enqueue and dequeue functions i.e. dequeue - if the number running is now less than two cancel the timer and otherwise decrease the expiry time to maintain the linear relationship of the interval with the number of runnable tasks enqueue - if the number of runnable tasks is now 2 then start the time with a single interval setting and if the number is greater than two then increase the timer interval to maintain the linear relationship. I'm assuming here that
add_timer(),del_timer()and (especially)mod_timer()are relatively cheap. Ifmod_timer()is too expensive some alternative method could be devised to maintain the linear relationship.Naive schemes reprogram the timer device too frequently.
I had a look at mod_timer() and I agree that it's too expensive to call every time a task gets queued or dequeued.
Quoted 4 lines
Software
constructs are less of a concern. This also presumes that taking timer interrupts when cpu-intensive workloads voluntarily yield often enough is necessary or desirable.
Voluntary yielding can't be relied upon. Writing a program that never gives up the CPU voluntarily is trivial. Some have been known to do it without even trying :-)
Quoted 2 lines
This is not so in virtualized environments,
and unnecessary interruption of userspace also degrades performance.
Peter
Signature · 4 lines
Peter Williams [email protected] "Learning, n. The kind of ignorance distinguishing the studious." -- Ambrose Bierce
Quoted 3 lines · William Lee Irwin III
Quoted 3 lines
Software constructs are less of a concern. This also presumes that taking timer interrupts when cpu-intensive workloads voluntarily yield often enough is necessary or desirable.
Quoted 3 lines · Peter Williams
Voluntary yielding can't be relied upon. Writing a program that never gives up the CPU voluntarily is trivial. Some have been known to do it without even trying :-)
No reliance is implied. In such a scenario, the timers for timeslice expiry are always cancelled because userspace voluntarily yields first, so no timer interrupts are delivered. Should userspace fail to do so, timer interrupts programmed for timeslice expiry would not be cancelled.
-- wli
Quoted 9 lines · William Lee Irwin III
Quoted 3 lines · William Lee Irwin III
Quoted 3 lines
Software constructs are less of a concern. This also presumes that taking timer interrupts when cpu-intensive workloads voluntarily yield often enough is necessary or desirable.
On Thu, Aug 05, 2004 at 11:06:51AM +1000, Peter Williams wrote:
Quoted 7 lines
Quoted 1 line
Voluntary yielding can't be relied upon. Writing a program that never gives up the CPU voluntarily is trivial. Some have been known to do it without even trying :-)
No reliance is implied. In such a scenario, the timers for timeslice expiry are always cancelled because userspace voluntarily yields first, so no timer interrupts are delivered. Should userspace fail to do so, timer interrupts programmed for timeslice expiry would not be cancelled.
OK. My misunderstanding.
Peter
Signature · 4 lines
Peter Williams [email protected] "Learning, n. The kind of ignorance distinguishing the studious." -- Ambrose Bierce