Collective Optimization: A Practical Collaborative Approach: The Final Publication Is Available at
Collective Optimization: A Practical Collaborative Approach: The Final Publication Is Available at
[Link]
Collective Optimization: A Practical Collaborative
Approach
GRIGORI FURSIN and OLIVIER TEMAM
INRIA Saclay, France
HiPEAC members
Iterative optimization is a popular and ecient research approach to optimize programs using
feedback-directed compilation. However, one of the key limitations that prevented widespread
use in production compilers and day-to-day practice is the necessity to perform a large number of
program runs with the same dataset and environment (architecture, OS, compiler) to test many
dierent combinations of optimizations. In this article, we propose to overcome such a practical
obstacle using collective optimization, where the task of optimizing a program or tuning default
compiler optimization heuristic leverages the experience of many other users continuously, rather
than being performed in isolation, and often redundantly, by each user. During this unobtrusive
approach, performance information is sent to a central database after each run and statistically
combined with the data from all users to suggest most protable optimizations for a given program
and an architecture, or to gradually improve default optimization level of a compiler for a given
architecture.
In this article, we address two key challenges of collective optimization. We show that it is
possible to simultaneously learn and improve performance while avoiding long training phases.
We also demonstrate how to use our approach with static compilers to learn optimizations across
multiple datasets and architectures without even a reference run normally needed to compute
speedups over the baseline optimization by using static function cloning and dynamic adaptation.
We present a novel probabilistic approach based on competition among pairs of optimizations
(program reaction to optimizations) to enable optimization knowledge reuse and achieve nearly
the best possible iterative optimization performance. We implemented our technique in GCC
(widespread production open-source compiler that supports multiple architectures) and connected
it to a public collective optimization database at [Link] to gather prole and optimization
data continuously and transparently in realistic environments ranging from desktop PCs and
mobile systems to supercomputers and data centers.
Categories and Subject Descriptors: D.3.4 [Programming Languages]: Processors-Compilers;
optimization; B.8.2 [Performance and Reliability]: Performance Analysis and Design Aids;
C.4 [Computer Systems Organization]: Performance of Systems-Measurement techniques;
modeling techniques
A preliminary version of this research is described in Proceedings of the International Conference
on High Performance and Embedded Architectures and Compilers (HiPEAC09).
This work has been partially supported by the EU IST FP6 STREP MILEPOST Project
(035307) [Link-MILEPOST ] and Google Summer of Code Program09.
Authors address: [Link] (corresponding author), [Link], INRIA Saclay, 3, rue Jean Ros-
tand, Orsay, 91893, France; email:[Link]@[Link] or [Link]@[Link]
Permission to make digital/hard copy of all or part of this material without fee for personal
or classroom use provided that the copies are not made or distributed for prot or commercial
advantage, the ACM copyright/server notice, the title of the publication, and its date appear, and
notice is given that copying is by permission of the ACM, Inc. To copy otherwise, to republish,
to post on servers, or to redistribute to lists requires prior specic permission and/or a fee.
c 2010 ACM 1544-3566/2010/12-ART20$10.00
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
2
General Terms: Design, Languages, Measurement, Experimentation, Performance
Additional Key Words and Phrases: Collective optimization, iterative compilation, continuous op-
timization, statistical optimization, adaptive compiler, self-tuning computing systems, collective
optimization database, multiple datasets, program characterization, program reaction to opti-
mization, function cloning, runtime adaptation
1. INTRODUCTION
Many recent research eorts have shown how iterative compilation can outperform
static compiler optimizations and quickly adapt to complex processor architectures
obtaining signicant performance improvements [Whaley and Dongarra 1998; Mat-
teo and Johnson 1998; Bodin et al. 1998; Cooper et al. 1999; Kisuki et al. 2000;
Fursin et al. 2002; Cooper et al. 2002; Kulkarni et al. 2003; Triantafyllis et al.
2003; Singer and Veloso 2000; Pan and Eigenmann 2004; 2006; Hoste and Eeck-
hout 2008]. Over the years, the approach has been perfected with fast optimization
space search techniques, sophisticated machine-learning algorithms, and continu-
ous optimization [Voss and Eigenmann 2000; Monsifrot et al. 2002; Stephenson
et al. 2003; Lu et al. 2004; Lattner and Adve 2004; Franke et al. 2005; Stephenson
and Amarasinghe 2005; Zhao et al. 2005; Agakov et al. 2006; Qasem et al. 2006;
Cavazos et al. 2007; Bailey et al. 2008; Fursin et al. 2008; Dubach et al. 2009].
Nevertheless, empirical iterative optimization is far from mainstream in production
environments. Besides the usual inertia for adopting novel approaches, there are
hard technical hurdles which hinder the adoption of iterative approaches.
One of the key challenges is that iterative techniques almost always rely on a
large number of training runs (either from the target program or other training
programs) to learn the best candidate optimizations. Moreover, all these runs
must be performed with the same programs, generated with the same compiler
on the same architecture with the same datasets, and repeated a large number of
times (tens, hundreds, or thousands of times) in order to deduce the shape of the
optimization space. Naturally, in practice, a user can rarely aord execution of
the same dataset multiple times, will change architectures every so often, and may
eventually upgrade a compiler as well. We believe this practical issue of collecting
a large number of training information, relying only on production runs (as opposed
to training runs where produced results are not used) to achieve good performance
is the crux of the slow adoption of iterative techniques in real environments.
We propose to address this issue with the notion of collective optimization. The
principle is to consider that the task of optimizing a program is not an isolated
task performed by each user separately, but a collective task where users can mu-
tually benet from the experience of others. Collective optimization makes sense
because most of the programs executed in servers, data centers, and cloud comput-
ing systems or that we use daily on our mobiles and desktop PCs are also run by
many other users, either globally if they are general tools or within one or a few
institutions if they are more domain specic.
Achieving collective optimization requires to solve both an engineering and a
research issue. The engineering issue is that users should be able to seamlessly
share the outcome of their runs with other users, without slowing down execution
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
3
or compilation, should support statically compiled programs, and should avoid
complicating compiler usage. The key research issue is that we must progressively
improve overall program and compiler performance while, at the same time, we
learn how programs react to the various optimizations using production runs. In this
approach training phase and test/use phase occur simultaneously unlike traditional
iterative compilation. Hence, we must understand whether or not it is possible and
how to learn across datasets, programs or platforms at the same time. An associated
research issue is to develop a knowledge representation scheme that is relevant
across datasets, programs, and platforms. Finally, because a user will generally
run a dataset only once, we must learn the impact of optimizations on program
performance without even a reference run to decide whether selected optimizations
improve or degrade performance compared to the baseline optimization.
In this article, we show that it is possible to continuously learn across datasets,
programs, or platforms, relying solely on production runs, and progressively im-
prove overall performance across runs, reaching close to the best possible iterative
optimization performance, itself achieved under idealized (and nonrealistic) condi-
tions. We show that extensively relying on statistical competition among pairs of
optimizations provides a robust and ecient method for capturing the impact of op-
timizations on program performance, without requiring reference runs to calculate
speedups and while remaining relevant across datasets, programs, and architec-
tures. While most recent research studies are focused on learning across programs
[Stephenson and Amarasinghe 2005; Agakov et al. 2006; Cavazos et al. 2007; Fursin
et al. 2008; Dubach et al. 2009], we found that in the case of collective optimization,
learning across datasets, and to a lesser extent, across architectures, is signicantly
more important and useful. Finally, we present a solution to the engineering is-
sue in the form of an extension to GCC with collective optimization plugins which
we connected to a central optimization repository through public Web services at
[Link] [Link-repository ; Link-ICI ; Fursin 2009] to eectively distribute opti-
mization process among many users, aggregate multiple proling and optimization
data, and perform program behavior characterization and continuous competitions
between optimizations during runs.
2. EXPERIMENTAL SETUP
Benchmarks, datasets, and architectures used throughout the article are briey
introduced in this section.
Benchmarks and datasets. In order to perform a realistic evaluation of col-
lective optimization, each benchmark has to come with several datasets in order to
emulate truly distinct runs. To our knowledge, only the MiDataSets/cBench bench-
mark and dataset suite [Fursin et al. 2007; Link-MiDatasets ; Fursin 2009] based
on the MiBench [Guthaus et al. 2001] currently provides more than 20 datasets for
each of the 26 benchmarks.
Compiler and proler. All programs are optimized using the GCC 4.2.0 com-
piler; several benchmarks (qsort, dijkstra, patricia, stringsearch) had to be
modied in order to successfully compile with GCC. The collective optimization
approach and framework are compatible with other compilers, but GCC is now be-
coming a competitive optimizing compiler with a large number of program transfor-
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
4
mation techniques and support for more than 30 dierent families of architectures.
We currently use the standard gprof tool to prole programs at function level.
This tool may introduce some overhead which we briey analyze in Section 5 and
suggest possible solutions to reduce it. We use the Interactive Compilation Interface
(ICI) [Link-ICI ; Fursin et al. 2008; Huang et al. 2010] to perform function cloning,
select combinations of optimizations per function and instrument programs. ICI is a
plugin system that acts as a middleware interface between production compilers
such as GCC and user-denable research plugins. The ICI framework provides
a high-level compiler-independent and a low-level compiler-dependent API that
open up and reuse the available functionality of production compilers in order to
transform them into stable, portable, and modular compiler research infrastructure
and enable interactive control of all internal decisions.
Optimizations. We selected 88 program transformations such as inlining, un-
rolling, scheduling, register allocation, constant propagation among many others
and which are known to inuence performance, and 8 parameters for each para-
metric optimization. One should bear in mind that GCC has not been originally
designed for research so it is not possible to explore the whole optimization space
by simply combining multiple compiler optimization ags, since some of them
are initiated only with a given global GCC optimization level (-Os,-O1,-O2,-O3).
We overcome this issue by selecting a global optimization level -O1 .. -O3 rst
and then either turning on a particular optimization through a corresponding ag
-f<optimization name> or turning it o using -fno-<optimization name> ag.
For our study, we selected 200 combinations of optimizations using a random
search strategy with 50% probability to select each ag and either turn it on or
o. We use this strategy to allow uniform unbiased exploration of unknown op-
timization search spaces. In order to validate the resulting diversity of program
transformations, we have checked that no two combinations of optimizations gen-
erated the same binary for any of the benchmarks using the MD5 checksum of
the assembler code obtained through objdump -d command. Occasionally, random
selection of ags in GCC may result in an invalid code. In order to avoid such
situations, we validated all generated combinations of optimizations by comparing
the outputs of all benchmarks used in our study with the recorded outputs during
reference runs when compiled with -O3 global optimization level.
Platforms. The programs were compiled and run on three distinct architectures:
AMD Athlon XP 2800+ (AMD32) - 5 machines, AMD Athon 64 3700+ (AMD64)
- 16 machines, and Intel Xeon 2.80GHz (IA32) - 2 machines.
Collective Optimization Database. We gradually make all our experimen-
tal data publicly available through the online collective optimization database at
[Link] repository [Link-repository ] to help end-users improve their computing
systems and help researchers reproduce the experimental results.
3. MOTIVATION
The performance upper bound of iterative optimization. Because the ex-
perimental methodology of research in iterative optimization consists of running
many times the same program on the same dataset and on the same platform, it
can be interpreted as an idealized case of collective optimization, where the experi-
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
5
S
p
e
e
d
u
p
0.0
0.5
1.0
1.5
2.0
s
u
s
a
n
_
e
s
u
s
a
n
_
c
s
u
s
a
n
_
s
t
if
f
m
e
d
ia
n
is
p
e
ll
r
ijn
d
a
e
l_
d
b
it
c
o
u
n
t
p
a
t
r
ic
ia
r
ijn
d
a
e
l_
e
p
g
p
_
e
C
R
C
3
2
jp
e
g
_
c
d
ijk
s
t
r
a
jp
e
g
_
d
q
s
o
r
t
a
d
p
c
m
_
c
t
if
f
d
it
h
e
r
t
if
f
2
b
w
g
h
o
s
t
s
c
r
ip
t
b
lo
w
f
is
h
_
e
b
lo
w
f
is
h
_
d
p
g
p
_
d
s
t
r
in
g
s
e
a
r
c
h
la
m
e
t
if
f
2
r
g
b
a
m
a
d
a
d
p
c
m
_
d
g
s
m
(a)
1.71
1
1.1
1.2
1.3
1.4
1.5
S
p
e
e
d
u
p
(b)
Fig. 1. (a) Distribution of speedups for all benchmarks and datasets. (b) Performance upper
bound of collective optimization averaged across datasets (AMD Athlon 64 3700+; GCC 4.2.0;
88 program transformations applied globally; 200 iterations with random search strategy; 50%
probability to select each transformation; speedups computed over the highest GCC optimization
level -O3).
ence of others (program, dataset, platform) would always perfectly match the target
run, in other words, a case where no experimental noise would be introduced by dif-
ferences in datasets, programs, or platforms. Consequently, iterative optimization
can be considered as a performance upper bound of collective optimization.
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
6
-O1 -falign-loops=10 -fpeephole2 -fschedule-insns -fschedule-insns2 -fno-tree-ccp -fno-tree-
dominator-opts -funroll-loops
-O1 -fpeephole2 -fno-rename-registers -ftracer -fno-tree-dominator-opts -fno-tree-loop-
optimize -funroll-all-loops
-O2 -nline-functions -fno-tree-dce -fno-tree-loop-im -funroll-all-loops
-O2 -fno-guess-branch-probability -fprefetch-loop-arrays -nline-functions -fno-tree-ter
-O2 -fno-tree-lrs
-O2 -fpeephole -fno-peephole2 -fno-regmove -fno-unswitch-loops
-O3 -nline-limit=1481 -falign-functions=64 -fno-crossjumping -fno-ivopts -fno-tree-
dominator-opts -funroll-loops
-O3 -nline-limit=64
-O3 -fno-tree-dominator-opts -funroll-loops
-O3 -frename-registers
-O3 -fsched-stalled-insns=19 -fschedule-insns -funroll-all-loops
-O3 -fschedule-insns -fno-tree-loop-optimize -fno-tree-lrs -fno-tree-ter -funroll-loops
-O3 -funroll-all-loops
-O3 -funroll-loops
Table I. Some of the Best combinations of GCC ags for MiBench across all datasets on
AMD64 (these are pruned combinations of optimizations where ags that do not inuence per-
formance have been removed)
The violin graphs in Figure 1(a) show the distribution of the speedups for all
benchmarks and datasets for AMD64 when applying 200 random combinations of
optimizations over the highest GCC optimization level (-O3). Figure 1(b) shows the
best speedup achieved for each benchmark averaged over 20 distinct datasets. The
combinations of optimizations corresponding to the best speedups across all pro-
grams and datasets are presented in Table I or can be found online at [Link]
repository [Link-repository ].
1
The diversity of compiler optimizations involved
demonstrates that the compiler optimization space is not trivial; the compiler best
optimization heuristic (-O3) is far from optimal and half of the benchmarks can
achieve more than 20%speedup after iterative compilation. Interestingly, some indi-
vidual transformations have to be turned o in order to achieve higher speedup that
can also help to reduce compilation time. The benchmarks that have sharp peaks of
speedup density usually require the longest time to obtain the best speedup. Over-
all, these experiments implicitly show that collective optimization has the potential
to yield high speedups if it is possible to learn from the experience of others.
It seems possible but not straightforward to learn from the experience
of others. Let us illustrate and quantify the diculty of learning from the expe-
rience of others by using a simple strategy, comparable to what users would do:
selecting the best optimization for a given context (dataset, program, architecture)
and applying it to another context. Next, we consider learning across datasets,
programs, and architectures.
We consider learning across datasets rst. In Figure 2, for each program, we
select the dataset (among 20) which exhibits the best speedup, and apply the corre-
sponding combination of optimizations to all other datasets. We then report the %
dierence between this performance and the best performance obtained for each
1
The ags that do not inuence performance have been iteratively removed from the original
combination of random optimizations to simplify the analysis of the results.
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
7
19
10
20
30
40
1
3
5
7
9
11
13
15
17
19
0
Fig. 2. Learning across datasets.
dataset. While programs like susan e can almost perfectly learn across datasets,
for other programs like dijkstra,patricia,adpcm c, the best optimizations for a
given dataset can yield much lower than optimal performance for other datasets.
This observation further conrms other similar experiments using the commercial
compiler PathScale [Fursin et al. 2007].
We performed similar experiments for programs. We selected the combination of
optimizations which yields the best performance averaged over the 20 datasets of
each program; see reference in Figure 3 (these combinations are listed in Table I).
Then, we apply all the best combinations to all other programs (see applied
to) and report the performance dierence (again averaged over the 20 datasets). A
program like susan c, which is fairly stable across data sets seems to behave poorly
using the best combinations of other programs. Conversely, the best combination
for patricia, a program which does not easily learn across datasets, provides a
good trade-o for many programs.
Finally, we performed similar experiments again for the three aforementioned
architectures (AMD64, AMD32, and IA32). Performance is again averaged over all
datasets, and we rst select the best combination of optimizations for a given pro-
gram on one of the architectures: AMD64. Then, we apply this combination to the
other two architectures, and report the performance dierence in Figure 4. Not sur-
prisingly, AMD32 exhibits the closest performance behavior to AMD64, while the
discrepancy between IA32 and AMD64 performance is likely due to their architec-
tural dierences. Again, these simple observations suggest that experience gathered
on an architecture is potentially useful but cannot always straightforwardly apply
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
8
Reference
A
p
p
l
i
e
d
t
o
bitcount
qsort
susan_c
susan_e
susan_s
jpeg_c
jpeg_d
tiff2bw
tiff2rgba
tiffdither
tiffmedian
dijkstra
patricia
ghostscript
ispell
stringsearch
blowfish_d
blowfish_e
pgp_d
pgp_e
rijndael_d
rijndael_e
CRC32
adpcm_c
adpcm_d
b
i
t
c
o
u
n
t
q
s
o
r
t
s
u
s
a
n
_
c
s
u
s
a
n
_
e
s
u
s
a
n
_
s
j
p
e
g
_
c
j
p
e
g
_
d
t
i
f
f
2
b
w
t
i
f
f
2
r
g
b
a
t
i
f
f
d
i
t
h
e
r
t
i
f
f
m
e
d
i
a
n
d
i
j
k
s
t
r
a
p
a
t
r
i
c
i
a
g
h
o
s
t
s
c
r
i
p
t
i
s
p
e
l
l
s
t
r
i
n
g
s
e
a
r
c
h
b
l
o
w
f
i
s
h
_
d
b
l
o
w
f
i
s
h
_
e
p
g
p
_
d
p
g
p
_
e
r
i
j
n
d
a
e
l
_
d
r
i
j
n
d
a
e
l
_
e
C
R
C
3
2
a
d
p
c
m
_
c
a
d
p
c
m
_
d
% difference with best performance
0% 60%
Fig. 3. Learning across programs.
to another architecture, even if the compiler platform is identical, as is the case
here.
4. COLLECTIVE OPTIMIZATION OVERVIEW
This section provides an overview of the proposed approach for collective optimiza-
tion. The general principle is that performance data about each run is transparently
collected and sent to a collective optimization database; and, after each run, based
on all the knowledge gathered so far, a new combination of optimizations is selected
and the program is recompiled accordingly. The key issue is which combination of
optimizations to select for each new run, in order to both gather new knowledge
and keep improving average program performance as we learn.
In collective optimization, several global and program-specic probability distri-
butions capture the accumulated knowledge. Combinations are randomly selected
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
9
0
5
10
15
20
25
30
35
40
45
b
i
t
c
o
u
n
t
q
s
o
r
t
s
u
s
a
n
_
c
s
u
s
a
n
_
e
s
u
s
a
n
_
s
j
p
e
g
_
c
j
p
e
g
_
d
t
i
f
f
2
b
w
t
i
f
f
2
r
g
b
a
t
i
f
f
d
i
t
h
e
r
t
i
f
f
m
e
d
i
a
n
d
i
j
k
s
t
r
a
p
a
t
r
i
c
i
a
g
h
o
s
t
s
c
r
i
p
t
i
s
p
e
l
l
s
t
r
i
n
g
s
e
a
r
c
h
b
l
o
w
f
i
s
h
_
d
b
l
o
w
f
i
s
h
_
e
p
g
p
_
d
p
g
p
_
e
r
i
j
n
d
a
e
l
_
d
r
i
j
n
d
a
e
l
_
e
C
R
C
3
2
a
d
p
c
m
_
c
a
d
p
c
m
_
d
%
D
i
f
f
e
r
e
n
c
e
w
i
t
h
b
e
s
t
p
e
r
f
o
r
m
a
n
c
e
AMD32
IA32
Fig. 4. Attempting to learn across architectures: % dierence of the best speedup achieved for
a given program on AMD32 and IA32 (averaged across all datasets) with the speedup obtained
when applying best found combination of optimizations for a program on AMD64.
from one of several probability distributions which are progressively built at the
remote server.
The dierent maturation stages of a program. For each program, and
depending on the amount of accumulated knowledge, we distinguish three scenarios:
(1) the server may not know the program at all (new program), (2) only have
information about a few runs (infrequently used or a recently developed program),
or (3) have information about many runs.
Stage 3: Program well known, heavily used. At this maturation stage, enough
runs have been collected for that program that it does not need the experience of
other programs to select the most appropriate combinations of optimizations for
itself. This knowledge takes the form of a program-specic probability distribution
called d
3
. Stage 3 corresponds to learning across datasets.
Stage 2: Program known, a few runs only. At this maturation stage, there is still
insucient information (program runs) to correctly predict the best combinations
by itself, but there is already enough information to start characterizing the
program behavior. This characterization is based on the comparison of the impact
of combinations of optimizations tried so far on the program against their impact
on other programs (program reaction to optimizations). If two programs behave
alike for a subset of combinations, they may well behave alike for all combinations.
Based on this intuition, it is possible to nd the best matching program, after
applying a few combinations to the target program. Then, the target program
probability distribution d
2
is given by the distribution d
3
of the matching program.
This matching can be revisited with each additional information (run) collected for
the target program. Stage 2 corresponds to learning across programs.
Stage 1: Program unknown. At this stage, almost no run has been performed,
so we leverage and apply optimizations suggested by the general experience col-
lected over all well-known programs. The resulting d
1
probability distribution is the
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
10
unweighted average of all d
3
distributions of programs which have reached Stage 3.
Stage 1 is an elementary form of learning across programs and allows us to auto-
mate and simplify the tuning of the default compiler optimization heuristic using
realistic programs, datasets and collective knowledge from multiple users instead
of ad hoc, repetitive training with some dedicated and not always representative
benchmarks.
Selecting stages. A program does not follow a monotonic process from Stage
1 to Stage 3, even though it should intuitively mature from Stage 1 to Stage 2
and then to Stage 3 in most cases. There is a permanent competition between the
dierent stages distributions (d
1
, d
2
, d
3
). At any time, a program may elect to draw
combinations of optimizations from any stage distribution, depending on which one
appears to perform best so far. In practice and on average, we nd that Stage 3
(learning across datasets) is by far the most useful stage. Stage 1 and Stage 2 are
respectively useful in the rst ten, and the rst hundreds of runs of a program on
average, but Stage 3 rapidly becomes dominant. The competition between stages
is implemented through a meta distribution d
m
, which reects the current score
of each stage distribution for a given program. Each new run is a two-step random
process: rst, the server randomly selects the distribution to be used, and then, it
randomly selects the combination using that distribution. How scores are computed
is explained in Section 6. Using that meta-distribution, the distribution with the
best score is favored.
5. COLLECTIVE OPTIMIZATION FRAMEWORK
In Figure 5, we show the collective optimization framework and two key compo-
nents to enable continuous aggregation and reuse of optimization knowledge: col-
lective compiler and collective optimization database (repository hosted at cTun-
[Link] [Link-repository ]).
Collective compiler. Our collective compiler is based on GCC with the Inter-
active Compilation Interface (ICI) [Link-ICI ; Fursin et al. 2008; Huang et al. 2010].
ICI abstracts the optimization process from a particular production compiler and
helps us reuse the same collective optimization framework with other compilers.
The extended compiler functionality and ICI collective optimization plugins allow
to clone functions, instrument programs to select original functions or clones at
runtime, control internal decisions, apply optimizations on a function level, and
intercept main and exit routines to collect proling statistics and send it to the
optimization repository or obtain a new combination of optimizations to improve
a program based on collective knowledge.
Usage scenarios. The collective optimization framework is compatible with the
original unmodied GCC and invokes collective optimization plugins only when a
user decides to participate in the collective learning by setting an environment
variable CTUNING to nonzero value. Currently, the collective compiler supports
two optimization scenarios: training mode with a reference run and production
mode with transparent runtime evaluation of optimizations using function cloning.
In both cases, the compiler adds gprof proling routines to a compiled program,
produces clones of all or only the most time consuming functions (if this statistic is
available after several executions) and applies some combinations of optimizations
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
11
Save profile statistics
and query server for
better optimization
User
X
Program
A
Architecture
B
Collective Compiler
Binary
Dataset
1
Dataset
N
Internet/Intranet
Web Server
Collective Optimization
Web Services
- Register events
- Query database
- Get statistics
Collective Optimization
Database
- COMPILATION table
- EXECUTION table
- AUXILARY tables
- Pool of validated
random optimizations
MySQL
Execution
User
Y
Program
C
Architecture
D
- Profiling Routines
- Collective Stats
- Unique IDs
Intercept exit() and call
Collective Stats Handler
Collective Optimization Server
([Link]
Initiate recompilation if better optimization setting
is suggested based on Collective Knowledge
Prolog of the time consuming code
Start profiling and
Randomly select version
(original or clone)
Original code
(Optimizations
1
)
Cloned code
(Optimizations
2
)
Stop profiling
Function clones
with different
optimizations
GCC with Interactive
Compilation Interface:
- create code clones
- instrument program
- apply optimizations per
clone
- intercept main()and
add auxiliary routines
Epilog of the time consuming code
Select validated combination of
optimizations
Fig. 5. Collective iptimization framework.
to both original and cloned functions through ICI.
During training mode invoked by setting CTUNING variable to 1, a program is
executed at least twice with the same dataset (similar to traditional iterative com-
pilation approaches [Fursin et al. 2008]) to be able to correctly evaluate the eect
of optimizations on the execution time. It is used for automatic oine search for
protable combinations of optimizations for a given architecture using standard
benchmarks, programs, and datasets. This approach can be used along with col-
lective optimization to speed up learning. Moreover, since the compiler sometimes
generates an invalid random combination of optimizations, our training mode can
reduce such risks and help to validate the correctness of a given combination by
comparing the original and new outputs of a program on a number of datasets.
A similar validation technique is commonly used in current compilers including
GCC. On the collective optimization server, we gradually build a pool of validated
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
12
optimizations favoring the best performing ones as shown in Table I, for example.
During production mode, invoked by setting CTUNING variable to 2, a pro-
gram is compiled with random combinations of optimizations validated during the
training mode and applied to both original and cloned functions. During con-
tinuous production runs of this program at data centers, PCs, mobiles, or other
computing systems, random combinations of optimizations are statistically evalu-
ated at runtime as described in Section 6. Furthermore, this and other proling
statistics are sent to the collective optimization server to both help other users im-
prove their systems and return better optimization suggestions based on collective
knowledge. A user can turn o this mode at any time by unregistering the envi-
ronment variable CTUNING when reasonable performance improvement is achieved
or when executing condential programs. In this case, a user can either recom-
pile the original program with the best found combination of optimizations while
removing clones and proling routines, or use the latest modied binary that will
automatically invoke clones with the best optimizations and skip proling and com-
munication with the collective optimization server. In the latter scenario, the user
may later easily resume the collective learning process.
S
l
o
w
d
o
w
n
1.0
1.2
1.4
1.6
1.8
2.0
2.2
b
it
c
o
u
n
t
is
p
e
ll
q
s
o
r
t
b
lo
w
f
is
h
_
d
b
lo
w
f
is
h
_
e
m
a
d
r
ijn
d
a
e
l_
e
p
a
t
r
ic
ia
r
ijn
d
a
e
l_
d
g
h
o
s
t
s
c
r
ip
t
t
if
f
d
it
h
e
r
jp
e
g
_
c
jp
e
g
_
d
a
d
p
c
m
_
c
d
ijk
s
t
r
a
p
g
p
_
e
t
if
f
2
b
w
p
g
p
_
d
s
t
r
in
g
s
e
a
r
c
h
t
if
f
2
r
g
b
a
t
if
f
m
e
d
ia
n
s
u
s
a
n
_
s
a
d
p
c
m
_
d
s
u
s
a
n
_
e
s
u
s
a
n
_
c
C
R
C
3
2
g
s
m
la
m
e
Fig. 6. Distribution of slowdown for all benchmarks and datasets due to gprof function-level
proling overheads (AMD64).
Proling. We decided to use standard gprof proling routines for execution
time per function and number of calls. Though this tool introduces some overhead
as shown in Figure 6, for half of the used benchmarks it is negligible and it is
used only for the proof of the concept and to simplify the implementation. In the
future, we plan to minimize this overhead by using our own optimized routines to
obtain cycle-accurate proling through performance counters or using tools such as
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
13
oprofile with nonintrusive proling through sampling [Link-OProle ]. Also, as
mentioned earlier, a user can turn o collective optimization mode with proling
at any time and leave the best found combination of optimizations.
During proling, we select the most time-consuming program routines (in this
work we select up to 3 functions that cover 75% or more of the execution time in our
benchmarks). The denition of the top routines can change across runs. Therefore,
we progressively build an average ranking of the program routines, possibly learning
new routines as they are exercised by dierent datasets.
METHODDEF(boolean)
decode_mcu (j_decompress_ptr cinfo, JBLOCKROW
*MCU_data) {
(Original function)
METHODDEF(boolean)
decode_mcu (j_decompress_ptr cinfo, JBLOCKROW
*MCU_data) {
if ((rand() % 2) == 0)
return decode_mcu1 (cinfo, MCU_data);
else
return decode_mcu2 (cinfo, MCU_data);
}
(Modified function to select clones randomly at
run-time)
METHODDEF(boolean)
decode_mcu1 (j_decompress_ptr cinfo, JBLOCKROW
*MCU_data) {
METHODDEF(boolean)
decode_mcu2 (j_decompress_ptr cinfo, JBLOCKROW
*MCU_data) {
(Two clones to compare combinations of
optimizations C1 and C2)
Fig. 7. Function cloning to evaluate combinations of optimizations transparently or to enable
dynamic adaptation for statically compiled programs.
Cloning. We modied GCC to implement function cloning. That required
changes in the core of the compiler since we had to implement full replication of
parts of a program AST. This functionality is controlled by the interactive com-
pilation interface. When collective optimization plugins trigger GCC to clone a
function, it inserts proling calls at the prolog and epilog of the function, replaces
static variables, and inserts additional instructions to randomly select either the
original or the cloned version as shown in Figure 7 for function decode mcu of
jpeg d. This enables continuous transparent evaluation of combinations of op-
timizations at runtime for statically compiled programs as described in detail in
Section 6.
Transparently collecting runtime information and reoptimizing. In or-
der to unobtrusively collect information on a program run, and reoptimize the
program, we modied GCC to intercept the compilation of the main() function,
and insert another interceptor on the exit() function to call a termination rou-
tine. Whenever the program execution nishes, this routine is invoked and it in
turn checks whether the Collective Stats Handler exists, invokes it to send compi-
lation and execution information to the collective optimization server and database
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
14
[Fursin 2009].
COMPILE_ID 17053973767718039
PLATFORM_ID 2111574609159278179
ENVIRONMENT_ID 2781195477254972989
COMPILER_ID 7548127843267843
PROGRAM_ID 37097459005644868
DATE 2007-07-09
TIME 18:32:43
OPT_FLAGS decode_mcu1={-O3 }
decode_mcu2={-O3 -fno-inline-functions
-fno-tree-ccp -fmove-loop-invariants}
COMPILE_TIME 3.4
BIN_SIZE 356655
OBJ_MD5CRC a420280c164310a47e2d8655028d1a66
(compilation stage)
RUN_ID 5572268172923323
COMPILE_ID 17053973767718039
PLATFORM_ID 2111574609159278179
ENVIRONMENT_ID 2781195477254972989
PROGRAM_ID 37097459005644868
DATE 2007-07-09
TIME 18:32:52
OUTPUT_CORRECT 1
RUN_TIME 10.32
RUN_TIME_USER 8.94
RUN_PROFILE {decode_mcu1=3.16, calls=139223}
{decode_mcu2=3.21, calls=142948}
(execution stage)
Fig. 8. Example of information packets sent to the Collective Optimization Server/Database
(hosted at [Link]) for the program jpeg d.
Figure 8 shows compilation and execution information packets sent to the database
for the program jpeg d. Each computer system is assigned several unique identi-
ers (generated by the UUID tool unless such system already exists in the collective
optimization database) describing architecture, environment, and compiler utilized.
Compilation and execution information packets as well as a program are also as-
signed unique IDs to allow easy distributed sharing and referencing of optimization
cases between multiple users. One should note that the OUTPUT CORRECT eld is used
only during the training mode when a program can be executed with the same
dataset more than once and program outputs can be compared to minimize the risk
of invalid combinations of optimizations as described earlier. Only validated com-
binations of optimizations can be later used for transparent optimizations without
a reference run.
When starting the optimization process, a user can either provide a program ID if
such a program has already been registered in the collective optimization database,
or use a tool we provide to dene the program ID as the MD5 checksum of compiled
source les. Eventually, after a few runs, we characterize programs using a portable
method based on dynamic features, as described in details in Section 6.2.
The termination routine queries a Web service on the collective optimization
server in order to obtain potentially better combination of optimizations for future
runs. If such combinations exist, a recompilation takes place periodically (period
set by the user) in the background, between several runs.
2
At any time, the user
can opt in or out of collective optimization by setting or resetting an environment
variable CTUNING.
Security. The concept of collective optimization raises new issues, especially
security. Therefore, we never send any source code to the collective optimization
2
Note that if the recompilation is not completed before another run starts, this latter run just
uses the same optimizations as the previous run, and the evaluation of the new optimizations is
just slightly delayed by one or a few runs.
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
15
server (only MD5 or dynamic features vectors). If a user would like to submit
optimization data from some privacy-critical applications to the common reposi-
tory, we provide an option to obfuscate program and function names. Furthermore,
the collective optimization server supports both public and private databases (for
companies). Note that companies can then get the best of both worlds: lever-
age/read information accessible from the common database, while recording infor-
mation about their runs solely to their private database.
6. COLLECTIVE LEARNING
In this section, we explain in more detail how to compute the aforementioned
distributions to achieve collective learning.
6.1 Building the Program Distribution d
3
Using Statistical Comparison of Combina-
tions of Optimizations
Comparing two combinations C
1
, C
2
. In order to build the aforementioned dis-
tributions, one must be able to compare the impact of any two combinations of
optimizations C
1
, C
2
on program performance. However, even the simple task of de-
ciding whether C
1
> C
2
can become complex in a real context. Since the collective
optimization process only relies on production runs, two runs usually correspond
to two distinct datasets. Therefore, if two runs with respective execution times T
1
and T
2
, and where combinations of optimizations C
1
and C
2
have been respectively
applied, are such that T
1
< T
2
, it is not possible to deduce that C
1
> C
2
.
To circumvent that issue, we perform runtime comparison of two combinations
of optimizations using cloned functions. C
1
and C
2
are respectively applied to the
clones f
1
and f
2
of a function f. At runtime, for each call to f, either f
1
or f
2
is
called; the clone called is randomly selected using an additional branch instruction
and a simple low-overhead pseudorandom number generation technique emulating
uniform distribution. We have shown in [Fursin et al. 2005] the possibility to
evaluate optimizations for statically compiled programs with stable behavior using
function cloning and runtime low-overhead phase detection. [Stephenson 2006]
and [Lau et al. 2006] demonstrated how to evaluate dierent optimizations for
programs with irregular behavior in dynamic environments using random function
invocations and averaging collected time samples across a period of time. We
combined these techniques to enable transparent runtime performance evaluation
for statically compiled programs with any behavior here. Even if the workload of
the routine varies upon each call, we observed that in many cases, if the routine
is executed a large number of times (> 100), the average workload performed by
each randomly selected clone can be similar during one execution. As a result,
the nonoptimized versions of f
1
and f
2
account for about the same fraction of the
overall execution time of f. Therefore, if the average execution time of the clone
optimized with C
1
is smaller than the average execution time of the clone optimized
with C
2
, it is often correct to deduce that C
1
is better than C
2
, that is, C
1
> C
2
.
This statistical comparison of combinations of optimizations requires no reference,
test or training run, and the overhead is negligible.
Naturally, it is not always possible to use the preceding technique to evaluate two
combinations of optimizations if there are only a few invocations of the function
during the whole program execution, if the workload varies considerably across
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
16
invocations, or there is too much noise during proling. Therefore, we continuously
monitor the speedups across runs until the speedup converges to some constant
value. Otherwise, a user has to resort to other evaluation methods, such as an
additional reference run with the same dataset, as for the training mode.
0.6 0.8 1.0 1.2 1.4 1.6 1.8
speedup
d
e
n
s
i
t
y
0.6 0.8 1.0 1.2 1.4 1.6 1.8 0.6 0.8 1.0 1.2 1.4 1.6 1.8 0.6 0.8 1.0 1.2 1.4 1.6 1.8
average
O3 vs O3, after 10 runs
O3 vs O3, after 100 runs
O3 vs best, after 10 runs
O3 vs best, after 100 runs
Fig. 9. Speedup convergence during runtime comparison of combinations of optimizations across
multiple runs of jpeg d with random datasets on IA32.
For example, Figure 9 demonstrates how the speedups for the hot function
decode mcu of jpeg d evolve during runtime comparison of optimizations across
multiple program executions with random datasets on IA32 using two scenarios. In
the rst scenario, decode mcu is compiled with the baseline optimization level (-O3)
while its clone is compiled with the top performing combination of optimizations.
In the second scenario, both original function and its clone are compiled with -O3.
The solid and dashed line show the evolution of the density of speedups after 10 and
100 program runs for the rst and second scenario, respectively. This experiment
demonstrates that in both scenarios the average speedup gradually converges to
some constant value and in the second scenario the average speedup converges to
1.0 thus conrming the possibility to use our runtime approach to compare opti-
mizations for this program and function.
Computing d
3
. When two combinations C
1
and C
2
are compared on a program
using the aforementioned cloned routines, the only information recorded is whether
C
1
> C
2
or C
1
< C
2
. Implicitly, a run is a competition between two combinations of
optimizations, and the winning combination scores 1, the other 0, as shown in Fig-
ure 10. These scores are cumulated for each combination and program. The scores
are then normalized per combination, by the number of times the combination was
tried (thus implicitly decreasing the average score of the losing combination). Then
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
17
the overall distribution is normalized so that the sum of all combinations scores
(probabilities) is 1. Note that we also experimented with scoring using
TimeC
1
TimeC
2
1
instead of 0/1 depending on C
1
> C
2
, which should provide a potentially richer,
program, dataset, and platform-dependent information, but found no signicant
performance benet. As a result, we decided to use more the independent, and
thus potentially more robust information.
1 2 3 4 5
Combinations of optimizations
After 1 iteration
(1 < 2)
0
0.2
After N
iterations
1 2 3 4 5 1 2 3 4 5
Fig. 10. Computing the probability distribution used for selecting a combination of optimizations.
Because this distribution only reects the relative merit of each combination,
and not the absolute performance (e.g., execution time or speedup), it is a fairly
resilient metric, tolerant to variations in measurements.
6.2 Building the Matching Distribution d
2
Stage 2 is based on the intuition that it is unlikely that all programs exhibit widely
dierent behavior with respect to compiler optimizations, or conversely that, once
the database is populated with a sucient number of programs, it is likely that a
new program may favor some of the same combinations of optimizations as some of
the programs already in the database. The main diculty is then to identify which
programs best correspond to the current target one. Therefore, we must somehow
characterize programs, and this characterization should reect which combinations
of optimizations a program favors.
As for d
3
, we use the metric-independent comparison between two combinations
of optimizations C
1
and C
2
. For example, C
1
> C
2
is a reaction to program opti-
mizations and is used as one characterization of the program. Let us assume that
C
1
> C
2
for the target program P and C
1
> C
2
for a program P
and C
1
< C
2
for
a program P
a score of
0. The program with the best score is considered the matching program, and d
2
is
set to the d
3
of that program. In other words, for d
2
we use a competition among
it programs. The more pairs (reactions to optimizations) are compared, the more
accurate and reliable the program matching.
Still, we observed that beyond 100 characterizing pairs of combinations of opti-
mizations (out of C
2
100
=
200
199
/2 = 19900 possible pairs of combinations), perfor-
mance barely improves. In addition, it would not be practical to recompute the
ACM Transactions on Architecture and Code Optimization, Vol. 7, No. 4, December 2010.
18
matching upon each run based on an indenitely growing number of characteri-
zations. Therefore, we restrict the characterization to 100 pairs of combinations,
which are collected within a rolling window (FIFO). However, the window only con-
tains distinct pairs of combinations of optimizations. The rolling property ensures
that the characterization is permanently revisited and rapidly adapted if neces-
sary. The matching is attempted as soon as one characterization is available in
the window, and continuously revisited with each new modication of the rolling
window.
[Cavazos et al. 2006] have shown that it is possible to improve similar program
characterizations by identifying and then restricting to optimizations which carry
the most information using the mutual information criterion. However, these op-
timizations do not necessarily perform best; they are the most discriminatory and
one may not aord to test them in production runs. Moreover, we will later see
that this approach could only yield marginal improvement in the start-up phase
due to the rapid convergence of Stage 3/d
3
.
6.3 Building the Aggregate Distribution d
1
d
1
is simply the average of all d
3
distributions of each program. d
1
reects the
most common cases: which combinations of optimizations perform best in general.
For example, it can be already used to systematically and continuously improve
default optimization level of a given compiler on a given architecture by distributing
the tuning process among many users and taking into account real applications
and datasets thus avoiding specialized and often limited benchmarks. So even
users not relying on collective optimization could benet in a simple way from the
collective knowledge gathered by others. Furthermore, it is also possible to compose
more restricted aggregate distributions, such as per architecture, per compiler, per
programs, or dataset subsets. We leave this for the future work.
6.4 Scoring Distributions
As mentioned in Section 4, a meta-distribution is used to select which stage distri-
bution is used to generate the next combination of optimizations. For each run, two
distributions d and d