Research Paper Review Report
No More Backstabbing... A Faithful Scheduling Policy for Multithreaded Programs
Kishore Kumar Pusukuri, Rajiv Gupta, Laxmi N. Bhuyan
Department of Computer Science and Engineering
University of California, Riverside
Riverside, USA 92521
[email protected], [email protected], [email protected]
Abstract—Efficient contention management is the key to achieving scalable performance for multithreaded applications running on multicore systems. However, contention manage- ment policies provided by modern operating systems increase context-switches and lead to performance degradation for multithreaded applications under high loads. Moreover, this problem is exacerbated by the interaction between contention management policies and OS scheduling polices. Time Share (TS) is the default scheduling policy in a modern OS such as OpenSolaris and with TS policy, priorities of threads change very frequently for balancing load and providing fairness in scheduling. Due to the frequent ping-ponging of priorities, threads of an application are often preempted by the threads of the same application. This increases the frequency of involuntary context-switches as wells as lock-holder thread preemptions and leads to poor performance. This problem becomes very serious under high loads.
To alleviate this problem, in this paper, we present a scheduling policy called Faithful Scheduling (FF), which dra- matically reduces context-switches as well as lock-holder thread preemptions. We implemented FF on a 24-core Dell PowerEdge R905 server running OpenSolaris.2009.06 and evaluated it using 22 programs including the TATP database application, SPECjbb2005, programs from PARSEC, SPEC OMP, and some microbenchmarks. The experimental results show that FF policy achieves high performance for both lightly and heavily loaded systems. Moreover it does not require any changes to the application source code or the OS kernel.
Keywords-Scheduling; priorities; contention; context- switches
I. INTRODUCTION
The advent of multicore architectures provides an attractive
opportunity for achieving high performance for a wide
variety of multithreaded applications. However, exploiting
the system density, and the parallelism they offer, to improve
performance of multithreaded applications is a challenging
task. This is because multithreaded application performance is
sensitive to the implementations of synchronization primitives
and contention management policies. Therefore the key
to achieving high performance for multithreaded applica-
tions running on multicore systems is to use appropriate
synchronization primitives along with efficient contention
management policies. Contention management policies are
either based on spinning, or blocking, or a combination
of both. Spinning resolves contention by busy waiting,
therefore waiting threads respond to lock handoffs very
quickly. However, spinning threads can wastes CPU resources
and prevent the lock-holder thread from running and releasing
the lock [1], [3], [6]. This dramatically degrades performance
and becomes a prominent problem in systems under high
load conditions. In contrast, the blocking scheme reschedules
waiting threads and allows other threads to use the system
resources. However, blocking scheme increases context-
switches, overloads OS scheduler, and thus leads to poor
performance [1], [3], [6].
To alleviate the above problems with spinning and blocking,
several hybrid schemes have been introduced. The adaptive
mutex provided by OpenSolaris [3], Linux futex [17], and
pthread mutex provided by pthread library are examples
of such hybrid schemes. Both Solaris adaptive mutex and
Linux futex use the state-of-the-art spin-then-block contention
management policy. According to this policy, threads spin if
the lock-holder thread is running on another CPU and block
otherwise. This policy is based on the assumption that mutex
hold times are typically short enough that the time spent
spinning is less than the time it takes to block [3]. However,
this policy faces challenges in providing optimal balance
between spinning and blocking because this balance must
change with increasing core and thread counts [1], [2].
Next we illustrate the above problem using the SPEC
OMP program applu. Fig. 1 shows the speedup and the
3 4
5 6
7
# Threads
S p
e e
d u
p
lSpeedup CX−Rate
l
l
l
l
l
l
6 12 18 24 36 48
2 3 0 0 0
5 0 0 0 0
7 4 0 0 0
9 8 0 0 0
1 2 2 0 0 0
C X
− R
a te
OPT
Figure 1: Speedup of applu degrades while CX-Rate increases as thread count grows on a 24-core machine. 24 threads represents 100% load.
context-switch (CX) rate observed by running applu on 24-
core machine for varying number of threads. The speedup is
computed relative to the serial execution-time. Applu achieves
the best performance with 18 threads on our 24-core machine.
As we can see, speedup of ‘applu’ drops while CX-Rate
increases as thread count grows. The implementation of
applu is based upon pthreads and pthread mutex uses the
state-of-the-art spin-then-bock contention management. As
we discussed above, as load (thread count) increases, the
spin-then-block policy increases the CX-Rate, overwhelms
the OS scheduler, causing poor performance even with 75%
load (.e., 18 threads). Applu is a contention-bound program
that experiences high CX-Rate and spends around 47% of its
elapsed time in lock-contention even with #threads < #cores,
i.e., less than 100% load.
The CX-Rate increases further because of the unwanted
interactions between the spin-then-block policy and the Time
Share (TS) scheduling policy which is the default scheduling
policy in a modern OS. With TS scheduling policy, priorities
of threads change very frequently for balancing load and
providing fairness in scheduling. Priority adjustments are
made based on the time a thread spends waiting for processor
resources, consuming processor resources, etc. [3]. Therefore,
at any execution point of a multithreaded application, some
of the threads belonging to the application get higher priority
while the others get lower priority. This leads to preemption
of low-priority threads by the high-priority threads of the
same application which often includes lock-holder thread
preemptions. This is what we call “Backstabbing” (BS)
which leads to increased frequency of involuntary context-
switches (ICXs), i.e. context-switches that cause threads to
be involuntarily taken off a core. Whenever a lock-holder
thread is preempted, the threads that are spinning for that lock
will be blocked, which in turn increases voluntary context-
switches (VCXs), i.e. context-switches that happen when a
threads fail to acquire a lock or are blocked due to IO. The
changes in context-switch rates lead to further changes in
thread priorities. Thus, the interaction between the state-of-
the-art spin-then-block policy and the TS scheduling policy
creates a vicious cycle between priority changes and context-
switches, which causes a drastic increase in CX-Rate (ICX-
Rate + VCX-Rate) with increasing load; thus leading to poor
performance.
To alleviate the problems with the state-of-the-art con-
tention management policies, Johnson et al., [1] proposed a
“load control” mechanism that decouples load management
from contention management. This approach uses blocking
to control the number of runnable threads and then spinning
in response to contention. Although this approach works well,
it needs to modify the applications for making spin locks
visible, it is sensitive to spikes in the load, and it does not
function well when priority inversions occur due to nested
critical sections [1]. Moreover, the implementation of the load
controller uses 7 ms as an update interval, with which, it is
difficult to obtain accurate processor-usage statistics, and the
overhead increases linearly with the number of threads [1].
However, unlike the above approach, in this paper we
present a new scheduling policy called faithful scheduling
(FF), where all threads of an application have same priority
for the entire execution. FF allocates the same time-quantum
to all the threads belonging to one application; however,
its value varies according to application’s usage of system
resources. By providing same priority to all the threads
of an application, this policy completely eliminates BS,
breaks the vicious cycle between thread priority changes
and context-switches, dramatically reduces CX-Rate, and
thus leads to high performance. By completely eliminating
BS, FF policy makes all the threads of an application fair to
each other. FF policy is agnostic to dynamic load changes
and improves performance predictability. The overhead of
the FF policy is negligible and it is an attractive approach
as it requires no changes to the application source code or
the OS kernel. Moreover, since it completely avoids priority
inversion problems and thus handles nested critical sections
well.
We implemented FF on a 24-core Dell PowerEdge
R905 server running OpenSolaris and evaluated it using
22 programs including the TATP database application [24],
SPECjbb2005 [27], programs from PARSEC [26], SPEC
OMP [27], and a microbenchmark [1]. The experimental
results show that at 100% load, FF policy achieves more
than 10% performance improvement for five programs with
a maximum of 35% improvement, 4%-10% for six programs,
less than 4% for nine programs, and there is no improvement
for one program over TS policy. At 200% load, FF policy
achieves more than 10% performance improvement for eight
programs with a maximum of 107% improvement, 4%-10%
for six programs, less than 4% for seven programs over TS
policy. Furthermore, FF policy also achieves performance
improvements under light loads, i.e., less than 100% load.
The key contributions of this work are as follows:
• We identify the reasons behind the problems caused by
the interactions between the spin-then-block policy and
TS scheduling policy through an in-depth performance
analysis of several multithreaded programs on a 24-core
multicore system.
• We present a scheduling policy FF, which eliminates
lock-holder thread preemptions, dramatically reduces
context-switches over TS policy, and achieves high
performance for a wide variety of benchmarks for both
lightly and heavily loaded systems.
• Finally, we develop FF policy using simple utilities
available on a modern OS and it requires no changes
to the application source code or the OS kernel. It is
very effective against phase changes of the application,
it completely avoids spikes in the load, and improves
performance predictability. Moreover, it introduces neg-
ligible runtime overhead.
2
The remainder of this paper is organized as follows. Section II
explains the problems caused by the interactions between OS
scheduling and contention management policies. Section III
presents the implementation of FF policy in detail and
Section IV presents the experimental setup. Section V
describes the evaluation of FF policy against a wide variety
of benchmark programs. Related work and conclusions are
given in Sections VI and VII.
II. INTERACTION BETWEEN OS SCHEDULING AND
CONTENTION MANAGEMENT
This section explains how the interaction between con-
tention management policies and OS scheduling policies
hurts the performance of multithreaded programs running on
multicore systems.
Time Share (TS) is the default scheduling policy in a
modern OS such as OpenSolaris. With TS scheduling policy,
priorities of threads change very frequently for balancing load
and providing fairness in scheduling. Priority adjustments
are made based on the times a thread spends waiting for
processor resources, consuming processor resources, etc [3].
Therefore, at a given point in time, some of the threads
belonging to an application get higher priority while the
others get lower priority. This leads to preemptions of the
low-priority threads of an application by the high-priority
threads of the same application, i.e. ‘Backstabbing’ (BS).
BS often includes lock-holder thread preemptions which
increases the ICX rate. We can further divide ICX into two
types: time-quantum context-switches (TQE ICX) happen
because of time-quantum expiration; and preemption context-
switches happen when a higher priority thread preempts a
lower priority thread (HPP ICX).
As we can see in Fig. 2(a), applu program experiences a
high degree of HPP ICX (56% of total ICX) when it is run
with 24 threads on 24 cores (100% load). Using DTrace [5]
scripts, we observed that almost all of these HPP ICX are
caused by applu threads i.e., applu experiences around 55%
BS at 100% load. Here BS is specifically defined as % of HPP
ICX caused by the same application threads. This is because
HPP ICX is also caused by high priority system processes
��������� � ��
���
���
�� � �������� �� � ����� �
���
���
���� �� �������
����� � ! �� �� �������
Figure 4: The interactions between the TS policy and the spin- then-block policy create vicious cycles between priority changes and context-switches.
running along with the application threads. However, we
can expect that BS is the major portion of HPP ICX (i.e.,
HPP ICX ∼ BS) when load crosses 100%. As shown in
Figure 2(b), priority change-rate increases as load increases
and also a major portion of priority changes are due to HPP
ICX. Another important point to note is that ICX (HPP ICX
and TQE ICX) causes a major portion of VCX. Figure 2(c)
shows a drastic increase in HPP ICX as load crosses 100%.
Therefore, we can expect that the frequency of lock-holder
thread preemptions will increase once load crosses 100%.
Thus, frequent ping-ponging [3] of thread priorities increases
HPP ICX, specifically BS, which in turn increases CX-Rate
(ICX-Rate + VCX-Rate), and ultimately vicious cycle is
created between context-switches and priority changes.
As shown in Fig. 4, the TS policy changes priorities of
threads based on their usage of system resources. Frequent
ping-ponging of thread priorities leads to HPP ICX, i.e., force
the threads off the CPU, which often include lock-holder
threads. When a lock-holder thread is preempted then all
the threads that are waiting for that lock will be blocked,
i.e., generates VCX. Then threads will join the lock’s sleep
queue and their priorities will be changed based on their
waiting time in the sleep queue. Thus, this process repeats
continuously, increasing CX-Rate and priority change-rate,
and thus leads to poor performance.
2 4 6 8 10
0 5
0 1
0 0
1 5
0 2
0 0
2 5
0 3
0 0
Time (sec)
IC X
− R
a te
Total ICX HPP ICX
(a) HPP ICX occupies a major portion of total ICX.
0 5
0 0
1 0
0 0
1 5
0 0
2 0
0 0
2 5
0 0
3 0
0 0
# Threads
P ri
o ri
ty C
h a
n g
e R
a te
Total CX
HPP ICX
12 24 36 48
100%
200%
(b) HPP ICX leads to changes in thread priorities.
0 5
0 0
1 0
0 0
1 5
0 0
2 0
0 0
2 5
0 0
3 0
0 0
# Threads
IC X
− R
a te
Total ICX
HPP ICX
12 24 36 48
100%
(c) Drastic increase in HPP ICX as load crosses 100%.
Figure 2: Frequent changes in thread priority drastically increases context-switches and in turn context-switches lead to changes in thread priority. A vicious cycle is created between priority changes and context-switches.
3
A. Lock-contention vs Backstabbing (BS)
From the above observations, we can expect that high
contention applications suffer more from BS than contention-
free applications. This is because threads of high contention
application seriously compete for lock acquisitions leading
to high CX-Rate. Contention-free applications scale well
and typically they experience CX-Rate far lower than high
contention applications. To get a clear idea about this, we ran
three different benchmark programs (nearly contention-free,
medium contention, and high-contention) and observed how
BS varies along with thread count. Fig. 3 shows the results.
As shown in Fig. 3(a), swaptions is a nearly contention-
free program and it does not significantly suffer from BS. BS
is almost nil when the load is below 100% and small under
high loads. This is because when the load crosses 100%,
there are more chances of lock-holder thread preemptions
and also high HPP ICX. However, this becomes a prominent
problem for the high contention programs. As shown in Fig. 3
(b) and (c), programs fluidanimate and applu experience high
% of BS. As applu is a high contention program, it suffers
from high % of BS even under low loads. These observations
demonstrate two things: (1) BS rapidly increases under high
loads, specifically when the load crosses 100%, and (2) high
contention programs experience significant BS even when the
load is below 100%. Therefore, if we completely avoid BS
then we can minimize CX-Rate and improve performance. In
order to avoid BS completely, we need to break the vicious
cycle between priority changes and context-switches.
Thus, based on the above observations, in the next section,
we present a scheduling policy called faithful scheduling (FF),
which breaks the cycle between priority changes and context-
switches, completely eliminates BS, dramatically reduces
CX-Rate, and thus leads to higher performance.
III. FAITHFUL SCHEDULING POLICY (FF)
The previous section highlights the fact that the interactions
between contention management and OS scheduling create
vicious cycle between priority changes and context-switches,
which leads to poor performance. Therefore, to break the
vicious cycle and achieve high performance, we propose a
scheduling policy called Faithful Scheduling Policy (FF) with
the following key characteristics:
1) Same priority is assigned to all the threads of a given
application.
2) Time-quantum is allocated based on the resource usage
of the entire application, specifically based on lock-
contention and cache miss-ratio of the application.
By providing same priority to all the threads of an
application, FF policy completely avoids BS, dramatically
reduces CX-Rate, and leads to high performance. Since
priorities of all the threads of an application are same, FF
allocates equal time-quantum to all of them for reducing
unwanted TQE ICX. Moreover, this makes all the threads
of an application fair to each other. However, finding the
right time-quantum for an application is tricky. For this, via
extensive experimentation with a wide variety of benchmarks,
we derived a metric called “scaling-factor” and developed a
scaling-factor table that guides time quantum allocation.
A. Scaling-factor Table
Finding right time-quantum is very important to provide
fair allocation of CPU cycles for all the threads of a multi-
threaded application. Threads of a CPU-intensive and low
contention application heavily compete for CPU resources.
Therefore, it is appropriate to provide small time quantum for
both CPU-intensive and low contention application threads.
In this way no thread will wait for a long time for a CPU.
In contrast, it is appropriate to provide large time-quantum
for both high-contention and memory-intensive application
threads. In case of high-contention applications, large time-
quantum allows lock-holder thread to complete its work
quickly, release the lock, and allow other threads to make
progress. Moreover large time-quantum for contention bound
application threads reduces unwanted TQE ICX and also
reduces the lock acquisition overhead since a wakeup and a
context-switch are required before the blocking thread can
become the owner of the lock it requires [3]. Based on the
above observations, the metric scaling-factor is defined in
Eq. (1).
l l
l l
0 2 0
4 0
6 0
8 0
1 0 0
#Threads
% B
S
0 2 0
4 0
6 0
8 0
1 0 0
12 24 36 48
% L
o c k −
c o n te
n ti o n
l %BS
%Lock
(a) swaptions (No contention).
l
l
l
l
0 2 0
4 0
6 0
8 0
1 0 0
#Threads
% B
S
0 2 0
4 0
6 0
8 0
1 0 0
12 24 36 48
% L
o c k −
c o n te
n ti o n
l %BS
%Lock
100%
(b) fluidanimate (Medium contention).
l
l
l l
0 2 0
4 0
6 0
8 0
1 0 0
#Threads
% B
S
12 24 36 48
% L
o c k −
c o n te
n ti o n
0 2 0
4 0
6 0
8 0
1 0 0
l %BS
%Lock
100%
(c) applu (High contention).
Figure 3: Lock-contention vs BS (24 threads is 100% load).
4
Scaling-factor = 1 - max(Miss-ratio, Lock-contention) (1)
Where ‘Miss-ratio’ is last-level cache miss-ratio and ‘Lock-
contention’ is the percentage of time application threads
spend waiting for user locks, condition-variables, etc. Using
Miss-ratio we can identify whether an application is memory-
intensive or not.
By conducting experiments with a wide variety of multi-
threaded programs and different time-quanta, we developed
the scaling-factor table shown in Table I, in which the
time-quantum goes down as the scaling-factor goes up
(inspiration from the priority dispatcher tables [3] of modern
OS). More specifically, to derive the table, first we categorize
the applications as memory intensive, CPU intensive, high
contention, or low contention applications. Then we selected
a few of applications from each category -- a total of 8
out of 22 applications, and ran them with varying time-
quantum ranging from 10 ms to 400 ms. The scaling factor
table obtained was then used in our experiments for all 22
applications. The 8 applications used to populate the scaling
factor table are: streamcluster, swim, swaptions, ferret, apsi,
applu, art, and bodytrack.
Therefore, based on the application’s cache miss-ratio and
lock-contention, scaling-factor of the application is between
one and zero. For scalable applications such as CPU-intensive
and low-contention applications, scaling-factor is high and
close to one, and for non-scalable applications such as
high memory-intensive or high lock-contention applications,
scaling-factor is close to zero. One important point here
is that the scaling-factor value is for the entire application
not per thread. Based on the scaling-factor value, FF policy
allocates corresponding time-quantum to all the threads of
the application.
Table I: The Scaling-factor Table. The range of the scaling-factor is 0.10.
scaling-factor TQ(ms)
(0.01 -- 0.10) 250
(0.11 -- 0.20) 200
(0.21 -- 0.30) 150
(0.31 -- 0.40) 120
(0.41 -- 0.50) 100
(0.51 -- 0.60) 80
(0.61 -- 0.70) 50
(0.71 -- 0.80) 30
(0.81 -- 0.90) 20
(0.91 -- 1.00) 10
B. Dealing with phase changes
Some applications have multiple different phases or regions
and exhibit different usages of system resources over time.
Therefore, we need to continuously monitor the applications
and apply appropriate time-quantum according to the resource
usage of their current phase. However, among the 22
benchmark programs we studied, only a couple of programs
ammp and SPECjbb2005 show significantly two different
phases in their execution. For example, consider ammp
0 20 40 60 80 100
0 .0
0 .2
0 .4
0 .6
0 .8
1 .0
Time (sec)
M is
s −
ra ti o
0 .0
0 .2
0 .4
0 .6
0 .8
1 .0
L o c k −
c o n te
n ti o n
Miss−ratio Lock−contention
Phase 1 Phase 2
Figure 5: Phase changes of ammp. Here ammp is run with 24 threads. Lock-contention value 1 means application experiences lock-contention for 100% of the total elapsed time.
SPEC OMP program. As shown in Fig. 5, ammp has two
significantly different phases. While ammp experiences high
miss-ratio and high lock-contention in Phase-1 (i.e., for the
first 25 seconds), it experiences low miss-ratio and low lock-
contention in Phase-2. Therefore according to the scaling-
factor table, FF policy allocates large time-quantum for the
first 25 seconds, and small time-quantum for the rest of its
execution.
C. Dealing with pipeline parallelism
It is fine to allocate equal time-quantum to all the threads of
an application based on pure data-parallelism. This is because,
the threads of a data-parallelism application more or less do
the same work. However, it may not be appropriate to allocate
equal time-quantum to all the threads of an application that
uses pipelined parallelism because resource usage of the
threads from different pipeline stages may differ greatly.
However, our experiments with different pipeline parallel
applications reveal that allocating equal time-quantum to all
the threads also works well for pipeline parallel applications.
This is because the scaling-factor is calculated based on the
resource usage of the entire application, which allows to
account the overall effect of all the threads or the dominating
pipeline stage threads. For example, consider ‘ferret’ pipeline
parallel application from PARSEC benchmark. ferret is a
search engine which finds a set of images similar to a query
image by analyzing their contents. The program is divided
into six pipeline stages -- the results of processing in one
stage are passed on to the next stage. The stages are: Load,
Segment, Extract, Vector, Rank, and Out. The speedup of
ferret increases linearly starting from 6 threads to all the way
up to 63 threads even though only 24 cores are available.
The reason for the observed behavior is as follows. The Rank
stage performs most of the work and thus the speedup of
the application is determined by the Rank stage. Moreover
the other stages perform relatively little work and thus their
threads together use only a fraction of the compute power of
the available cores. Thus, as long as cores are not sufficiently
5
utilized, more speedup can be obtained by creating additional
threads for the Rank stage. Therefore, Rank stage threads of
ferret program dominates the behavior of all other threads
and represents resource usage of whole ferret program. Thus,
since the scaling-factor represents the resource usage of the
entire application, allocating time-quantum based on the
scaling-factor works well also for pipeline parallel programs.
D. Implementation of FF policy
There are two important components of the implementation
of FF policy framework: (1) providing same priority to all
the application threads, and (2) allocating appropriate time-
quantum based on the resource usage of the application.
OpenSolaris provides a scheduling class called Fixed Priority
scheduling [3]; with the combination of this class and
priocntl(1) [4] utility, we can allocate same priority to all the
threads of an application. However, there is no way to find
appropriate time-quantum for an application in OpenSolaris
with the fixed priority scheduling class. Moreover, this
class does not provide any capability for updating time-
quantum [3]. Thus, there is no way to deal with the phase
changes of an application. Therefore, in addition to devel-
oping a scaling-factor table, we also perform continuously
monitoring of an application to allocate appropriate time-
quantum according to its phase changes.
Let us consider the FF policy implementation in detail. As
shown in Algorithm 1, our implementation uses a daemon
thread. First we start the target program with the default TS
policy and start monitoring the program’s last-level cache
miss-ratio and lock-contention after the creation of target
program’s worker threads. We use cputrack(1) utility to
monitor miss-ratio and prstat(1) utility for lock-contention
with one second interval. We used a timer that fires a timer
signal for every one second and the framework catches
the signal and collects miss-ratio and lock-contention of
the target program with one second interval, calculates a
scaling-factor, and based on this it allocates appropriate
time-quantum to the application threads using the scaling-
factor table. More specifically, the framework measures a
scaling-factor of the target application for every one second,
and checks whether to change the time-quantum or not by
comparing the current scaling-factor with the previous one.
Although we can use an interval with milliseconds resolution,
we used one second interval because our experiments showed
that one second interval is enough to deal with the phase
changes of the programs studied in this work. Although,
one second time-interval is the minimum timeout value we
could have used with the default implementation of prstat(1)
utility, we modified this utility to allow time intervals with
millisecond resolution to monitor lock-contention. Therefore,
it is easy to use an interval less than one second for an
application that experiences rapid phase changes.
Thus, our framework continuously monitors the target
multithreaded program and allocates same priority using
Algorithm 1: FF Policy Framework
Profile Data Structure and Variables; Profile P:
missRatio: last-level cache misses/accesses; lockContention: (% lock-contention/100);
// range of the scaling-factor
range = 0.10;
Subroutines: getProfile():
Monitor missRatio using cputrack(1) and lockConetntion using prstat(1) of the target program with one second interval and return a Profile P;
getScalingFactor(missRatio, lockContention): return [1 - max(missRatio, lockContention)] ;
getTimeQuantum(scalingFactor): return corresponding TQ from the Scaling-Factor Table;
Input : Target Multithreaded Benchmark Program Output : Apply FF policy.
Start the target program with TS policy; while program hasn’t create its worker threads do
Sleep(); // checks like a deamon process end
Wait for one more second to allow the application threads for their initialization period;
oldP = getProfile(); oldScalingFactor = getScalingFactor(oldP.missRatio, oldP.lockContention); oldTQ = getTimeQuantum(oldScalingFactor);
Allocate oldTQ and same priority using priocntl(1) utility;
// continuous monitoring
repeat newP = getProfile(); newScalingFactor = getScalingFactor(newP.missRatio, newP.lockContention);
if (newScalingFactor > (oldScalingFactor + range)) or (newScalingFactor < (oldScalingFactor - range)) then
newTQ = getTimeQuantum(newScalingFactor); oldScalingFactor = newScalingFactor; Allocate newTQ using priocntl utility;
end until completion of the target program;
priocntl(1) utility and assigns appropriate time-quantum based
on the scaling-factor table. Moreover, the overhead of this
framework is negligible (0.02% of CPU utilization) and it
requires no changes to the application source code or to the
OS kernel.
IV. EXPERIMENTAL SETUP
This section describes the execution environment where
FF policy is developed and evaluated.
A. Target Machine and OS
Our experimental setup consists of a Dell PowerEdge R905
server whose configuration is shown in Table II. As we can
see this machine has 24 cores and is running OpenSolaris.
6
Table II: Target Machine and Operating System. DellTM PowerEdge R905:
24 Cores:
4 × 6-Core 64-bit AMD Opteron 8431 Processors (2.4 GHz);
L1 : 128 KB; Private to a core; L2 : 512 KB; Private to a core;
L3 : 6144 KB; Shared among 6 cores; Memory: 32 GB RAM;
Operating System: OpenSolaris.2009.06.
B. Benchmarks
We evaluate FF policy with a wide variety of benchmarks
-- 22 benchmark programs in all. We also included a micro-
benchmark [1] to study how FF policy works under varying
levels of contention. This benchmark consists of M threads
running on N cores that repeatedly acquire and release a
single global lock. The critical section consists of a single
call to gethrtime(), which takes around 300 ns to execute
on our machine. Between lock acquires, threads busy-wait a
fixed period of time before the first measurement and stop
after the last one. Threads increment a local counter with
each lock releases, and the benchmark harness computes
throughput by comparing two successive readings of each
thread’s counter while threads continue to run.
The other 21 complete programs are as follows: eight
programs (streamcluster, facesim, canneal, x264, fluidanimate,
swaptions, ferret, and bodytrack) from PARSEC [26], 11
programs (swim, wupwise, equake, gafort, art, apsi, ammp,
applu, fma3d, galgel, and mgrid) from SPEC OMP [27],
SPECjbb2005 [27], and TATP [24] database transaction
program. The implementations of PARSEC programs are
based upon pthreads and we ran them using native inputs.
SPEC OMP programs were run on medium input data sets.
SPECjbb2005 with single JVM is used in all our experiments.
TATP (a.k.a NDBB and TM-1) uses a 10000 subscriber
dataset of size 20MB with a solidDB [25] engine. TATP
is not IO-intensive and disk performance does not affect it
significantly [1]. In this work, we ran each experiment 10
times and present average results from the ten runs.
V. EVALUATING FF POLICY
In this section, we analyze the effectiveness of FF policy
using the microbenchmark and the 21 complete programs
introduced in Section IV.
A. Against varying contention levels
Since FF policy completely avoids BS and specifically
lock-holder thread preemptions, it is very effective against
varying lock-contention levels. Fig. 6 demonstrates this. We
use a microbenchmark where threads contend for a single
global lock, with a fixed delay between requests [1]. High
contention occurs for short requests on the left of the x-axis
and drops off moving toward the right. We consider three
cases, where the machine is 95% loaded (i.e., 23 threads),
150% loaded (i.e., 36 threads) and 200% loaded (i.e., 48
threads) [1]. As we move right along the x-axis, contention
decreases, and throughput is improved in all three cases. As
we can see in Fig. 6, when contention is high and the system
is overloaded, program experiences high BS, and leads to
poor performance. For lightly loaded systems, FF performs
N o
rm a
liz e
d T
h ro
u g
h p
u t
0 5 0 0
1 0 0 0
1 5 0 0
2 0 0 0
2 5 0 0
3 0 0 0 TS FF
Delay in lock requests (us)
20 30 50
95% 150% 200% 95% 150% 200% 95% 150% 200%
Figure 6: FF policy is very effective against varying contention levels.
slightly better than TS because program experiences low
BS. However, overall, FF outperforms TS significantly at all
contention levels.
B. Against phase changes
As explained in Section III-D, the FF framework con-
tinuously monitors the target multithreaded program and
allocates appropriate time-quantum to effectively deal with
its phase changes. For example, consider the ammp program
which exhibits two significantly different execution phases
described in Section III-B. Using the scaling-factor table,
the FF policy allocates appropriate time-quantum according
to the resource usage of its phases. As ammp suffers from
high lock contention for around 84% of elapsed time in the
first phase, scaling-factor is 0.16 for the first phase. Here
lock-contention is higher than miss-ratio value. Likewise,
scaling-factor is 0.88 for the second phase of the ammp
program as it suffers from low lock contention for around
12%. Therefore, using continuous monitoring, the FF policy
allocates time-quantum 200 ms for the first phase, 20 ms for
the second phase, and thus effectively deals with the phase
changes of the ammp program.
As shown in Fig. 7, FF policy is very efficient against the
phase changes of ammp program. It dramatically reduces
ICX-Rate and leads to high performance. As we can
see in Fig. 7(c), ammp achieves up to 15% performance
improvement with FF policy. Since, we use small time-
quantum for the phases that have high scaling-factor, we
can expect a little increase in TQE ICX. Thus, as we can see
in Fig. 7, there is a rise in the ICX-Rate in the second phase
with FF policy. However, FF policy produces less TQE ICX
compared to TS policy at both 100% and 150% loads.
C. Against dynamic load changes
Since FF policy completely eliminates BS, consequently
reducing CX-Rate, it brings stability in load management.
Fig. 8 demonstrates this. The y-axis of the figure represents
normalized run-queue length of the system, i.e. total number
of runnable threads on the dispatcher queues of the system [3],
[4]. The x-axis shows the time in seconds. Fig. 8 shows the
normalized run-queue lengths of swaptions, fluidanimate,
applu programs at 100%, 150%, and 200% loads. As shown
7
0 20 40 60 80 100
0 2
0 0
4 0
0 6
0 0
8 0
0 1
0 0
0 1
2 0
0
Time (sec)
IC X
− R
a te
TS
FF
(a) Dramatic reduction in ICX-Rate at 100% load.
0 20 40 60 80 100
0 2
0 0
4 0
0 6
0 0
8 0
0 1
0 0
0 1
2 0
0
Time (sec)
IC X
− R
a te
TS
FF
(b) Dramatic reduction in ICX-Rate at 150% load.
12 24 36 48
# Threads
% P
e rf
o rm
a n
c e
I m
p ro
v e
m e
n t
0 5
1 0
1 5
(c) Performance improvement over TS policy.
Figure 7: FF policy effectively deals with phases of ammp program and improves its performance.
l
l l l l
l
l l l
l
2 4 6 8 10
0 .9
8 1 .0
0 1 .0
2
100% Load
Time (sec)
N o
rm a
li z e
d R
u n
− q
u e
u e
L e
n g
th
l TS FF
l
l l l
l l
l l
l
l
2 4 6 8 10
1 1 .9
0 1 2 .0
0
150% Load
Time (sec)
N o rm
a li z e d R
u n −
q u e u e L
e n
g th
l
l l
l l
l
l
l l l
2 4 6 8 10
2 3 .9
0 2 3 .9
6
200% Load
Time (sec)
N o rm
a li z e d R
u n −
q u e u e L
e n g th
(a) swaptions (no contention).
l
l
l
l
l
l
l
l
l
l
2 4 6 8 10
0 .1
0 0 .2
0 0 .3
0
100% Load
Time (sec)
N o
rm a
li z e
d R
u n
− q
u e
u e
L e
n g
th
l TS FF
l
l
l
l
l
l
l
l
l
l
2 4 6 8 10
1 .5
2 .5
3 .5
150% Load
Time (sec)
N o rm
a li z e d R
u n −
q u e u e L
e n
g th
l
l
l
l
l
l
l l
l
l
2 4 6 8 10
5 .5
6 .5
7 .5
200% Load
Time (sec)
N o rm
a li z e d R
u n −
q u e u e L
e n g th
(b) fluidanimate (medium contention).
l
l l
l l l
l
l
l l
2 4 6 8 10
0 .3
0 0 .4
0 0 .5
0
100% Load
Time (sec)
N o
rm a
li z e
d R
u n
− q
u e
u e
L e
n g
th
l TS FF
l
l
l l
l l
l
l l l
2 4 6 8 10
1 2
3 4
5
150% Load
Time (sec)
N o rm
a li z e d R
u n −
q u e u e L
e n
g th
l l
l
l
l
l
l
l
l
l
2 4 6 8 10
2 6
1 0
1 4
200% Load
Time (sec)
N o rm
a li z e d R
u n −
q u e u e L
e n g th
(c) applu (high contention).
Figure 8: FF policy avoids spikes in the load.
in Fig. 8(a), there are no significant load changes with
both TS and FF policies in case of very low contention
swaptions program even at 200% load. However, there are
significant spikes in the load for high contention programs --
fluidanimate and applu -- with TS policy, but there are no
spikes in the load with FF policy. Therefore, by completely
eliminating BS and consequently reducing CX-Rate, FF
policy avoids spikes in the load and leads to high performance.
Moreover, threads experience higher CPU latencies with TS
policy under high loads compared with FF policy, i.e., threads
wait for longer times in the dispatch queues with TS policy,
which slows down the progress of the application.
Thus, FF policy is agnostic to dynamic load changes
and improves performance predictability of multithreaded
programs running on multicore machines. In contrast to this,
the load-controller [1] is sensitive to spikes in the load.
D. Performance Improvements
As shown in Fig. 9 and 10, FF policy improves per-
formance for a wide variety of programs at 50%, 100%,
150%, and 200% loads over TS policy. As high contention
programs suffer heavily from BS, they achieve tremendous
performance improvement with FF policy. Fig. 9(a), Fig. 10,
and Fig. 7(c) all show this. There are moderate improvements
for the medium contention programs shown in Fig. 9(b)
and small improvements for the low contention programs
shown in Fig. 9(c). Although FF policy considers whole
application for allocating time-quantum, as shown in Fig. 9(b)
and Fig. 9(c), FF policy improves performance of pipeline
parallel programs bodytrack, x264, and ferret.
More specifically, at 100% load, FF policy achieves
more than 10% performance improvement for five programs
with a maximum of 35% improvement, 4%-10% for six
programs, less than 4% for nine programs, and there is no
improvement for one program over TS policy. At 200%
load, FF policy achieves more than 10% performance
improvement for eight programs with a maximum of 107%
improvement, 4%-10% for six programs, less than 4% for
seven programs over TS policy. Moreover, FF policy also
achieves performance improvements for several programs
under light loads, specifically at 50% load.
Since our execution environment is different from [1],
it is not possible to directly compare the performance
improvement data of TATP using our FF policy against
the performance improvement with the load-controller [1].
However, as shown in Fig. 10 (c), FF policy improves
performance of TATP like the load-controller does and also
the performance degradation is steady as load increases.
Moreover, in contrast to the load-controller, we did not need
to modify the application source code for ensuring visible
spin locks and also FF policy is agnostic to dynamic load
changes.
8
% P
e rf
o rm
a n
ce I
m p
ro ve
m e
n t
0 1
0 2
0 3
0 4
0 5
0
fma3d equake apsi mgrid galgel applu
50% 100% 150% 200%
(a) High Performance Improvements.
% P
e rf
o rm
a n
ce I
m p
ro ve
m e
n t
0 2
4 6
8
50% 100% 150% 200%
wupwise fluidanimate gafort bodytrack x264
(b) Medium Performance Improvements.
% P
e rf
o rm
a n
ce I
m p
ro ve
m e
n t
0 2
4 6
8
50% 100% 150% 200%
art streamcluster ferret canneal swim swaptions
(c) Low Performance Improvements.
Figure 9: FF policy improves performance of a wide variety of programs.
36 42 45 48 60
# Threads
% P
e rf
o rm
a n
c e
I m
p ro
v e
m e
n t
0 2
4 6
8 1 0
(a) SPECjbb2005.
8 16 32 64
#Threads
% P
e rf
o rm
a n
c e
I m
p ro
v e
m e
n t
0 2
4 6
8 1
0 1
2 1
4
(b) facesim.
24 36 48
#Threads
N o
rm a
li z e
d T
h ro
u g
h p
u t
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 TS FF
(c) TATP
Figure 10: Performance improvement of SPECjbb2005, facesim, and TATP with FF policy. SPECjbb2005 creates 35 threads with one warehouse.
E. Discussion
The previous section demonstrates that FF policy improves
performance of a wide variety of multithreaded applications
at different loads. We next discuss some of the extensions
and limitations of FF policy framework.
1) Concurrent runs of more than one application
TS policy has been widely used in modern operating
systems. It does not consider the whole application but rather
assigns priority and time-quantum on a per thread basis. That
is why FF policy significantly outperforms TS policy when
single multithreaded application is running on the system.
However, TS policy is quite effective when there are multiple
multithreaded applications running on a multicore system.
Therefore, we would like to see how FF policy works with
parallel runs of more than one application on a multicore
system. For this, we conducted two experiments. In the first
experiment we ran applu with 24 threads along with extra
load offered by mgrid – we ran 24 threads of applu along with
12 threads, 24 threads, and 36 threads of mgrid. In the second
experiment we run both applu and mgrid with equal number
of threads – (12, 12), (18, 18), and (24, 24) threads. As shown
in Fig. 11 (a) and Fig. 11 (b), FF policy greatly outperforms
TS policy. Similar performance improvements resulted from
several experiments of running multiple applications with FF
policy. We are unable to present those due to lack of space.
Thus, FF policy is also effective when there is more than
one application running on the system.
2) Limitations
Although FF policy is quite effective against pipeline
parallel programs, still we can improve their performance
if we use different and appropriate time-quanta for different
S p
e e
d u
p
0 1
2 3
4 5
6
applu mgrid applu mgrid applu mgrid
50% 100% 150%
Extra load offered by mgrid
TS FF
(a) applu with extra load offered by mgrid.
S p
e e
d u
p
0 1
2 3
4 5
6
applu mgrid applu mgrid applu mgrid
100% 150% 200%
Total Load
TS FF
(b) Both applu and mgrid offer same load.
Figure 11: FF policy is very effective against parallel runs of more than one application.
pipeline stage threads according to their resource usage. The
22 applications studied in this work mainly stress CPU and
Memory. However, it is easy to extend FF policy framework
for IO-intensive applications by considering how much time
threads utilizing CPU, IO characteristics, and modifying the
scaling-factor table appropriately.
VI. RELATED WORK
The problems with spinning and blocking are well known
and have prompted many approaches, such as queue-based
spinlocks [7], [8] and ticket spinlocks [9], to alleviate these
problems. Both Queue-based spinlocks and ticket spinlocks
provide an efficient way of orderly lock-handoffs because
waiting threads form a FIFO queue and each lock handoff
targets a specific thread. However, they also suffer from
lock-holder thread preemptions at high load and create lock
convoys [1], [10]. Time-published locks [11] eliminate the
main problem with queue-based locks by only handing the
lock to running threads. However, these also allow lock
holders to be vulnerable to preemption [1]. By limiting the
number of waiting threads which can respond simultaneously,
backoff-based techniques [12], [13], [19] provide another
solution to the “thundering herd” problem [1], where all
waiting threads race for the lock at each release and cause
both contention and memory traffic. However, finding optimal
backoff length for the general case is a challenging problem.
Hybrid spin-then-block techniques [3], [17], [19] use spinning
to reduce context switching imposed by a blocking primitive.
However, these also face challenges to provide optimal
balance between spinning and blocking as load increases [2].
In order to avoid unexpected load changes because of
the interactions between irregular parallelism of database
9
applications and scheduling, several admission control tech-
niques [14], [15], [18] are employed. These techniques
monitor system statistics regarding CPU, memory, lock
contention and tune the amount of work allowed into the
system [1]. Using simulations, Gupta et al. [12] explored
the trade-offs between the use of busy-waiting and blocking
synchronization primitives and their interactions with the
scheduling strategies. They also explored the impact of
the scheduling strategies on the caching behavior of the
applications. Several researchers [20]–[23] use application
characteristics such as cache miss ratio to make better
scheduling decisions in multicore environments.
To alleviate the problems with the hybrid spin-then-
block approaches, Johnson et al., [1], [6] proposed a “load
control” mechanism that decouples load management with
the contention management. This approach uses blocking to
control the number of runnable threads and then spinning
in response to contention. Although this approach works
well, it needs to modify the applications for providing visible
spin lock and load controller is sensitive to large changes
in the load. It also faces problems when priority inversions
arise due to nested critical sections, it does not completely
eliminate BS, and leads to high CX-Rate as load increases.
Moreover, the implementation of load controller uses 7 ms
as an update interval, with which, it is difficult to obtain
accurate processor usage statistics and the overhead increases
linearly with the number of threads [1].
In contrast, in this work, we dramatically reduce the
problems caused by the unwanted interactions between OS
scheduling policy and contention management policy. We
presented a scheduling policy called faithful scheduling (FF),
where all threads of an application have same priority for
its entire execution, however the time-quantum is allocated
according to their usage of system resources. By providing
same priority to all the threads of an application, this policy
completely eliminates BS, dramatically reducing CX-Rate,
and leads to high performance. It avoids priority inversion
problems and therefore it is not effected by nested critical
sections. Moreover, FF policy avoids spikes in the load, it
does not require any modifications to application source
code, and its implementation is also simple with negligible
overhead.
VII. CONCLUSIONS
This paper presents a scheduling policy called Faithful
(FF) Scheduling, where threads of an application have same
priority and the time-quantum is allocated according to the
resource usage of the entire application. FF policy is very
effective against varying contention levels, phase changes,
dynamic load changes, and improves performance of a wide
variety of benchmark programs over the default scheduling
policy Time Share (TS). Moreover, FF policy is an attractive
approach as it does not require any changes to the application
source code or the OS kernel.
ACKNOWLEDGEMENTS
The authors would like to thank Antoni Wolski and Simo
Neuvonen of IBM Research for their help in installing the
TATP benchmark and Ryan Johnson of University of Toronto
for his help in developing the micro benchmark. Jim Mauro
and Rick Weisner of Oracle for their help throughout this
work. The authors would also like to thank the anonymous
reviewers for their helpful comments.
This work is supported in part by NSF grants CCF-
0963996 and CNS-0810906 to the University of California,
Riverside.
REFERENCES [1] R. Johnson, R. Stoica, A. Ailamaki, T. C. Mowry. Decoupling contention
management from scheduling. In ASPLOS 2010.
[2] L. Boguslavsky, K. Harzallah, A. Kreinen, K. Sevcik, A. Vainshtein. Optimal
strategies for spinning and blocking. Journal of Parallel and Distributed Com-
puting, Volume 21, Issue 2, PP. 246-254, May 1994.
[3] R. McDougall, J. Mauro. Solaris Internals, Prentice Hall Publications, Second
Edition, July 2006 .
[4] R. McDougall, J. Mauro, and B. Gregg. Solaris Performance and Tools: DTrace
and MDB Techniques for Solaris 10 and OpenSolaris, Prentice Hall, 2006.
[5] B. Cantrill, M. Shapiro, and A. Leventhal. Dynamic instrumentation of produc-
tion systems. In USENIX ATC, 2004.
[6] R. Johnson, M. Athannassoulis, R. Stoica, and A. Ailamaki. A new look at
the roles of spinning and blocking. In ACM SIGMOD DaMoN workshop,
Providence, RI, July 2009.
[7] J. M. Mellor-Crummey, M. L. Scott, Algorithms for scalable synchronization
on shared-memory multiprocessors, ACM TOCS 9,1, p.21-65, Feb. 1991.
[8] P. Magnussen, A. Landin, and E. Hagersten. Queue locks on cache coherent
multiprocessors. In International Symposium on Parallel Processing, pp. 165-
171, Apr. 1994.
[9] D. P. Reed and R. K. Kanodia. Synchronization with Event-counts and Se-
quencers. Communications of the ACM, 22(2):115-123, Feb. 1979.
[10] M. Blasgen, J. Gray, M. Mitoma, and T. Price. The convoy phenomenon. ACM
SIGOPS Operating Systems Review 13,2, pp. 20-25. 1979.
[11] B. He, W. N. Scherer III, and M. L. Scott. Preemption adaptivity in time-
published queue-based spin locks. In HiPC, 2005.
[12] A. Gupta, A. Tucker, and S. Urushibara. The Impact Of Operating System
Scheduling Policies And Synchronization Methods On Performance Of Parallel
Applications. SIGMETRICS Perform. Eval. Rev., 1995.
[13] A. Agarwal and M. Cherian. Adaptive backoff synchronization techniques. In
ISCA, pp. 396-406, 1989.
[14] N. Bartolini, G. Bongiovanni, Simone Silvestri. Self-*through self-learning:
Overload control for distributed web systems. In International Journal of
Computer and Telecommunications Networking 53,5, pp. 727-743, Apr. 2009.
[15] M. Carey, S. Krishnamurthi, and M. Livny. Load control for locking: the “half-
and-half” approach. In PODS, Apr. 1990.
[16] J. Carlstrom and R. Rom. Application aware admission control and scheduling
in web servers. In INFOCOM, 2002.
[17] H. Franke, R. Russell, M. K. Fuss. Futexes and furwocks: Fast userlevel locking
in linux. In Proc. 2002 Ottawa Linux Summit, 2002.
[18] A. Monkeberg, G. Weikum. Performance evaluation of an adaptive and robust
load control method for the avoidance of data contention thrashing. In VLDB,
1992.
[19] J. K. Ousterhout. Scheduling techniques for concurrent systems. In Dist. Com-
puting Systems, 1982.
[20] E. W. Parsons, K. C. Sevcik. Benefits of speedup knowledge in memory-
constrained multiprocessor scheduling. Performance Evaluation 27/28, pages
253-272, 1996.
[21] M. Bhadauria, S. A. McKee. An Approach to Resource-Aware Co-Scheduling
for CMPs. In ICS, June, 2010.
[22] Guangdeng Liao, Danhua Guo, Laxmi N. Bhuyan and Steve R. King. Software
Techniques to Improve Virtualized I/O on Multi-core Platforms. In proceedings
of ANCS 2008, San Jose, USA, 2008.
[23] S. Zhuravlev, S. Blagodurov and A. Fedorova. Addressing Shared Resource
Contention in Multicore Processors via Scheduling. In ASPLOS, 2010.
[24] IBM. Telecom Application Transaction Processing (TATP) Benchmark De-
scription. Available online at http://tatpbench-mark.sourceforge.net/TATP_
Description.pdf.
[25] IBM solidDB 6.5 Fix Pack 3 - 6.5.0.3 Build 2010-10-04 https://www-304.ibm.
com/support/docview.wss?uid=swg24028071
[26] C. Bienia, S. Kumar, J.P. Singh, and K. Li. The PARSEC Benchmark Suite:
Characterization and Architectural Implications. In PACT, 2008.
[27] SPEC OMP, SPECJbb2005. http://www.spec.org/
10