The Velocity Compiler: Extracting

Total Page:16

File Type:pdf, Size:1020Kb

The Velocity Compiler: Extracting THE VELOCITY COMPILER: EXTRACTING EFFICIENT MULTICORE EXECUTION FROM LEGACY SEQUENTIAL CODES MATTHEW JOHN BRIDGES ADISSERTATION PRESENTED TO THE FACULTY OF PRINCETON UNIVERSITY IN CANDIDACY FOR THE DEGREE OF DOCTOR OF PHILOSOPHY RECOMMENDED FOR ACCEPTANCE BY THE DEPARTMENT OF COMPUTER SCIENCE ADVISOR: PROF. DAVID I. AUGUST NOVEMBER 2008 c Copyright by Matthew John Bridges, 2008. All Rights Reserved Abstract Multiprocessor systems, particularly chip multiprocessors, have emerged as the predomi- nant organization for future microprocessors. Systems with 4, 8, and 16 cores are already shipping and a future with 32 or more cores is easily conceivable. Unfortunately, multi- ple cores do not always directly improve application performance, particularly for a single legacy application. Consequently, parallelizing applications to execute on multiple cores is essential. Parallel programming models and languages could be used to create multi-threaded applications. However, moving to a parallel programming model only increases the com- plexity and cost involved in software development. Many automatic thread extraction tech- niques have been explored to address these costs. Unfortunately, the amount of parallelism that has been automatically extracted using these techniques is generally insufficient to keep many cores busy. Though there are many reasons for this, the main problem is that extensions are needed to take full advantage of these techniques. For example, many important loops are not parallelized because the compiler lacks the necessary scope to apply the optimization. Additionally, the sequen- tial programming model forces programmers to define a single legal application outcome, rather than allowing for a range of legal outcomes, leading to conservative dependences that prevent parallelization. This dissertation integrates the necessary parallelization techniques, extending them where necessary, to enable automatic thread extraction. In particular, this includes an ex- panded optimization scope, which facilitates the optimization of large loops, leading to parallelism at higher levels in the application. Additionally, this dissertation shows that many unnecessary dependences can be broken with the help of the programmer using nat- ural, simple extensions to the sequential programming model. Through a case study of several applications, including several C benchmarks in the SPEC CINT2000 suite, this dissertation shows how scalable parallelism can be extracted. iii By changing only 38 source code lines out of 100,000, several of the applications were parallelizable by automatic thread extraction techniques, yielding a speedup of 3.64x on 32 cores. iv Acknowledgments First and foremost, I would like to thank my advisor, David August, for his assistance and support throughout my years in graduate school at Princeton. He has taught me a great deal about research, and I would not be here if not for his belief in me. Additionally, the strong team environment and investment in infrastructure that he has advocated has been a wonderful benefit. His continued expectation that I work to the best of my abilities has lead to this dissertation, and for that I am grateful. This dissertation was also made possible by the support of the Liberty research group, including Ram Rangan, Manish Vachharajani, David Penry, Thomas Jablin, Yun Zhang, Bolei Guo, Adam Stoler, Jason Blome, George Reis, and Jonathan Chang. Spyros Tri- antafyllis, Easwaran Raman, and Guilherme Ottoni have contributed greatly to the VE- LOCITY compiler used in this research and have my thanks for both their friendship and support. Special thanks goes to Neil Vachharajani, both for the many contributions to VE- LOCITY and this work, as well as for the many interesting discussions we have had over the years. I would like to thank the members of my dissertation committee, Kai Li, Daniel Lav- ery, Margaret Martonosi, and Doug Clark. Their collective wisdom and feedback have improved this dissertation. In particular, I thank my advisor and my readers, Kai Li and Daniel Lavery, for carefully reading through this dissertation and providing comments. Ad- ditionally, I thank my undergraduate research advisor, Lori Pollock, without whom I would not have entered graduate research. This dissertation would not be possible without material research support from the Na- tional Science Foundation, Intel Corporation, and GSRC. Special thanks also goes to Intel for summer internship that they provided and the guidance given to me by Daniel Lavery and Gerolf Hoflehner. Finally, I thank my friends and family. I thank my mother Betty, my father John, my step-father Doug, my mother-in-law Janet, and my father-in-law Russell, for having sup- v ported me throughout this process with their love and encouragement. Above all, my wife Marisa has my sincere thanks for putting up with everything involved in creating this dis- sertation and for reading early drafts. She has seen me through the good times and the bad and I would not have accomplished this with out her. vi Contents Abstract ....................................... iii Acknowledgments .................................. v List of Tables .................................... x List of Figures .................................... xi 1 Introduction 1 2 Automatic Parallelization 7 2.1 Extracting Parallelism ............................. 7 2.1.1 Independent Multi-Threading .................... 7 2.1.2 Cyclic Multi-Threading ....................... 9 2.1.3 Pipelined Multi-Threading ...................... 11 2.2 Enhancing Parallelism ............................ 13 2.2.1 Enhancing IMT Parallelism ..................... 13 2.2.2 Enhancing CMT Parallelism ..................... 16 2.2.3 Enhancing PMT Parallelism ..................... 19 2.3 Breaking Dependences with Speculation ................... 21 2.3.1 Types of Speculation ......................... 21 2.3.2 Speculative Parallelization Techniques ................ 22 2.3.3 Loop-Sensitive Profiling ....................... 27 2.4 Compilation Scope .............................. 28 vii 2.5 Parallelization For General-Purpose Programs ................ 30 3 The VELOCITY Parallelization Framework 33 3.1 Compilation and Execution Model ...................... 33 3.2 Decoupled Software Pipelining ........................ 34 3.2.1 Determining a Thread Assignment .................. 34 3.2.2 Realizing a Thread Assignment ................... 41 3.3 Parallel-Stage DSWP ............................. 46 3.3.1 Determining a Thread Assignment .................. 46 3.3.2 Realizing a Thread Assignment ................... 50 3.4 Speculative Parallel-Stage DSWP ...................... 56 3.4.1 Determining a Thread Assignment .................. 56 3.4.2 Realizing a Thread Assignment ................... 63 3.4.3 Loop-Aware Profiling ........................ 70 3.5 Interprocedural Speculative Parallel-Stage DSWP .............. 75 3.5.1 Determining a Thread Assignment .................. 75 3.5.2 Realizing the Thread Assignment .................. 78 4 Extending the Sequential Programming Model 85 4.1 Programmer Specified Parallelism ...................... 85 4.2 Annotations for the Sequential Programming Model ............. 87 4.2.1 Y-branch ............................... 88 4.2.2 Commutative ............................. 90 5 Evaluation of VELOCITY 94 5.1 Compilation Environment ........................... 94 5.2 Measuring Multi-Threaded Performance ................... 95 5.2.1 Emulation ............................... 96 5.2.2 Performance ............................. 96 viii 5.2.3 Cache Simulation ........................... 99 5.2.4 Bringing it All Together ....................... 99 5.3 Measuring Single-Threaded Performance .................. 100 5.4 Automatically Extracting Parallelism ..................... 100 5.4.1 256.bzip2 ............................... 100 5.4.2 175.vpr ................................ 104 5.4.3 181.mcf ................................ 106 5.5 Extracting Parallelism with Programmer Support .............. 109 5.5.1 164.gzip ................................ 109 5.5.2 197.parser ............................... 112 5.5.3 186.crafty ............................... 113 5.5.4 300.twolf ............................... 115 5.6 Continuing Performance Trends ....................... 117 6 Conclusions and Future Directions 122 6.1 Future Directions ............................... 123 ix List of Tables 3.1 DSWP ISA Extensions ............................ 42 3.2 PS-DSWP ISA Extensions .......................... 51 3.3 SpecPS-DSWP ISA Extensions ........................ 67 3.4 iSpecPS-DSWP ISA Extensions ....................... 82 5.1 Cache Simulator Details ........................... 99 5.2 Information about the loop(s) parallelized, the execution time of the loop, and a description. ............................... 117 5.3 The minimum # of threads at which the maximum speedup occurred. As- suming a 1.4x speedup per doubling of cores, the Historic Speedup column gives the speedup needed to maintain existing performance trends. The final column gives the ratio of actual speedup to expected speedup. ..... 120 x List of Figures 1.1 Normalized performance of the SPEC 92, 95, and 2000 integer benchmarks suites. Each version of the suite is normalized to the previous version using matching hardware. Only the highest performance result for each time period is shown. The solid line is a linear regression on all points prior to 2004, while the dashed line a linear regression on all points in or after 2004. Source data from SPEC
Recommended publications
  • Debloating Modern Java Applications a Thesis Submitted In
    UNIVERSITY OF CALIFORNIA Los Angeles JShrink: Debloating Modern Java Applications A thesis submitted in partial satisfaction of the requirements for the degree Master of Science in Computer Science by Jaspreet Singh Arora 2020 c Copyright by Jaspreet Singh Arora 2020 ABSTRACT OF THE THESIS JShrink: Debloating Modern Java Applications by Jaspreet Singh Arora Master of Science in Computer Science University of California, Los Angeles, 2020 Professor Miryung Kim, Chair Modern software is bloated. Demand for new functionality has led developers to include more and more features, many of which become unneeded or unused as software evolves. This phenomenon of software bloat results in software consuming more resources than it otherwise needs to. Automation of effective debloating is a long standing problem in soft- ware engineering. Various software debloating techniques have been proposed since the late 1990s. However, many of these techniques are built upon pure static analysis and have yet to be extended and evaluated in the context of modern Java applications where dynamic language features are prevalent. To this end, we develop an end-to-end bytecode debloating framework called JShrink. JShrink augments traditional static reachability analysis with dynamic profiling and type dependency analysis, and renovates existing byte-code transfor- mations to perform effective debloating. We highlight several nuanced technical challenges that must be handled properly to debloat modern Java applications and further examine behavior preservation of debloated
    [Show full text]
  • Subroutines and Control Abstraction8
    Subroutines and Control Abstraction8 8.4.4 Generics in C++, Java, and C# Though templates were not officially added to C++ until 1990, when the language was almost ten years old, they were envisioned early in its evolution. C# generics, likewise, were planned from the beginning, though they actually didn’t appear until the 2.0 release in 2004. By contrast, generics were deliberately omitted from the original version of Java. They were added to Java 5 (also in 2004) in response to strong demand from the user community. C++Templates EXAMPLE 8.69 Figure 8.13 defines a simple generic class in C++ that we have named an Generic arbiter class in arbiter. The purpose of an arbiter object is to remember the “best instance” C++ it has seen of some generic parameter class T. We have also defined a generic chooser class that provides an operator() method, allowing it to be called like a function. The intent is that the second generic parameter to arbiter should be a subclass of chooser, though this is not enforced. Given these definitions we might write class case_sensitive : chooser<string> { public: bool operator()(const string& a, const string& b){returna<b;} }; ... arbiter<string, case_sensitive> cs_names; // declare new arbiter cs_names.consider(new string("Apple")); cs_names.consider(new string("aardvark")); cout << *cs_names.best() << "\n"; // prints "Apple" Alternatively, we might define a case_insensitive descendant of chooser, whereupon we could write Copyright c 2009 by Elsevier Inc. All rights reserved. 189 CD_Ch08-P374514 [11:51 2009/2/25] SCOTT: Programming Language Pragmatics Page: 189 379–215 190 Chapter 8 Subroutines and Control Abstraction template<class T> class chooser { public: virtual bool operator()(const T& a, const T& b) = 0; }; template<class T, class C> class arbiter { T* best_so_far; C comp; public: arbiter() { best_so_far = 0; } void consider(T* t) { if (!best_so_far || comp(*t, *best_so_far)) best_so_far = t; } T* best() { return best_so_far; } }; Figure 8.13 Generic arbiter in C++.
    [Show full text]
  • Inlining in Gforth: Early Experiences
    Inlining in Gforth: Early Experiences David Gregg M. Anton Ertl∗ Trinity College Dublin TU Wien Abstract icant time1. Therefore, Forth compilers with their need for Many optimizations are easier or more effective for compilation speed have not embraced optimizations straight-line code (basic blocks). Straight-line code beyond basic blocks. E.g., RAFTS [EP96] and in Forth is limited mainly by calls and returns. In- (to our knowledge) VFX perform their optimiza- lining eliminates calls and returns, which in turn tions (e.g., register allocation) only at the basic makes the basic blocks longer, and increases the ef- block level. Cforth [Alm86] and (to the best of fectiveness of other optimizations. In this paper we our knowledge) iForth perform global register al- present a first prototype implementation of ininlin- location of a kind by continuing the current alloca- ing for Gforth. tion across branches and performing reconciliation at control flow joins (not necessarily in a close-to- optimal way). 1 Introduction Another reason why loop-level and global opti- mizations are not very useful for Forth is that the Many code generation tasks and optimizations are main cause of basic block boundaries in Forth is relatively easy to perform on basic blocks (code sec- calls and exits (see Fig. 1). tions with only one entry point and one exit), of- Therefore, if we want to optimize Forth signifi- ten with optimal results (with respect to some opti- cantly beyond basic blocks, it seems that we have to mality criterion). Examples are register allocation, perform interprocedural optimization, which is even static stack caching [EG04a], and superinstruction harder, more complicated and slower than global selection [EG03]; all of these problems are relevant optimization, and not as well researched.
    [Show full text]
  • The C++ Programming Language in Cheminformatics And
    Rassokhin J Cheminform (2020) 12:10 https://doi.org/10.1186/s13321-020-0415-y Journal of Cheminformatics REVIEW Open Access The C programming language in cheminformatics++ and computational chemistry Dmitrii Rassokhin* Abstract This paper describes salient features of the C programming language and its programming ecosystem, with emphasis on how the language afects scientifc++ software development. Brief history of C and its predecessor the C language is provided. Most important aspects of the language that defne models of programming++ are described in greater detail and illustrated with code examples. Special attention is paid to the interoperability between C and other high-level languages commonly used in cheminformatics, machine learning, data processing and statistical++ computing. Keywords: Programming languages, C, C , Scientifc computing, Computational chemistry, Cheminformatics ++ Introduction role of being the language that de-facto dominates mod- In recent years, a plethora of high-level domain-specifc ern scientifc software development, even though, at frst and general-purpose programming languages have been glance, this may not be so obvious. In this paper, we will developed to greatly increase the productivity of pro- briefy describe the history of C++ and focus on its main grammers working on various types of software projects. characteristics that make it so special. Scientifc programming, which used to be dominated by Brief history of C and C Fortran up until about mid-1980s, now enjoys a healthy ++ choice of tools, languages and libraries that excel in help- Te predecessor of C++, C was developed in the early ing solve all types of problems computational scientists 1970s by Dennis M.
    [Show full text]
  • Reflecting on Generics for Fortran
    Reflecting on Generics for Fortran Magne Haveraaen∗∗ Jaakko Järvi∗ Damian Rousonyy July 23, 2019 Abstract This paper focuses on the benefits of a well-designed generics feature, and points out important design decisions for achieving those benefits. 1. A generics facility needs to be type safe, both for the developer and the user of generic code. 2. Built in (intrinsics) and user defined (derived) types and operations (functions/subrou- tines) need to be treated in the same way as generic arguments. 3. A generics facility needs to allow generic parameter lists to be extended/nested. The note does not discuss technicalities of a specific generics design. It is motivated by the upcoming Fortran discussion in Tokyo (JP) in August 2019. 1 Introduction For the upcoming IEC/ISO WG5 & ANSII J3 Fortran committee meeting in Tokyo August 5- 9 there are several proposals for adding a generics feature. Fortran currently lacks a generic mechanism to allow type and operation parameters to modules, classes and operations (functions and subroutines). This prevents Fortran from providing, e.g., reusable collection classes which are now a standard feature of most other mainstream programming languages. The design space of generics is large, evidenced by how different the generics features of different languages are (see some examples in Appendix A). This paper emphasises a few key demands for such a feature, based on observations of problems and successes of generics in various languages. These demands are crucial if one wishes to unleash the full potential of generic code reuse, going beyond the standard examples of generics (collection classes, etc.).
    [Show full text]
  • Instruction Fetching: Coping with Code Bloat
    To appear in the 22nd International Symposium on Computer Architecture, Santa Magherita Ligure, Italy, June, 1995. Instruction Fetching: Coping with Code Bloat Richard Uhlig David Nagle German National Research Center for Computer Science ECE Department, Carnegie Mellon University Schloβ Birlinghoven, 53757 Sankt Augustin, Germany 4902 Forbes Ave, Pittsburgh, PA 15213 [email protected] [email protected] Trevor Mudge and Stuart Sechrest Joel Emer EECS Department, University of Michigan Digital Equipment Corporation 1301 Beal Ave., Ann Arbor, Michigan 48109-2122 77 Reed Road HLO2-3/J3, Hudson, MA 01749 {tnm,sechrest}@eecs.umich.edu [email protected] Abstract trends on one important aspect of memory-system design: the fetching of instructions. Previous research has shown that the SPEC benchmarks As application and operating system software evolves to achieve low miss ratios in relatively small instruction caches. This include more features and to become more portable, maintainable paper presents evidence that current software-development prac- and reliable, it also tends to consume more memory resources. tices produce applications that exhibit substantially higher The “bloating” of code affects a memory-system hierarchy at all instruction-cache miss ratios than do the SPEC benchmarks. To levels and in a variety of ways: the larger static sizes of program represent these trends, we have assembled a collection of applica- executables occupy more disk space; the larger working sets of tions, called the Instruction Benchmark Suite (IBS), that provides bloated programs require more physical main memory; bloated a better test of instruction-cache performance. We discuss the programs use virtual memory in a more sparse and fragmented rationale behind the design of IBS and characterize its behavior manner, making their page-table entries less likely to fit in TLBs; relative to the SPEC benchmark suite.
    [Show full text]
  • Jshrink: In-Depth Investigation Into Debloating Modern Java Applications
    JShrink: In-Depth Investigation into Debloating Modern Java Applications Bobby R. Bruce∗ Tianyi Zhang∗ Jaspreet Arora University of California, Davis Harvard University University of California, Los Angeles U.S.A U.S.A U.S.A [email protected] [email protected] [email protected] Guoqing Harry Xu Miryung Kim University of California, Los Angeles University of California, Los Angeles U.S.A U.S.A [email protected] [email protected] ABSTRACT KEYWORDS Modern software is bloated. Demand for new functionality has Java bytecode, size reduction, reachability analysis, debloating led developers to include more and more features, many of which ACM Reference Format: become unneeded or unused as software evolves. This phenome- Bobby R. Bruce, Tianyi Zhang, Jaspreet Arora, Guoqing Harry Xu, and Miryung non, known as software bloat, results in software consuming more Kim. 2020. JShrink: In-Depth Investigation into Debloating Modern Java resources than it otherwise needs to. How to effectively and auto- Applications. In Proceedings of the 28th ACM Joint European Software En- matically debloat software is a long-standing problem in software gineering Conference and Symposium on the Foundations of Software Engi- engineering. Various debloating techniques have been proposed neering (ESEC/FSE ’20), November 8–13, 2020, Virtual Event, USA. ACM, New since the late 1990s. However, many of these techniques are built York, NY, USA, 12 pages. https://doi.org/10.1145/3368089.3409738 upon pure static analysis and have yet to be extended and evaluated in the context of modern Java applications where dynamic language 1 INTRODUCTION features are prevalent.
    [Show full text]
  • 1. Optimizing Software in C++ an Optimization Guide for Windows, Linux, and Mac Platforms
    1. Optimizing software in C++ An optimization guide for Windows, Linux, and Mac platforms By Agner Fog. Technical University of Denmark. Copyright © 2004 - 2021. Last updated 2021-08-11. Contents 1 Introduction ....................................................................................................................... 3 1.1 Why software is often slow .......................................................................................... 4 1.2 The costs of optimizing ............................................................................................... 4 2 Choosing the optimal platform ........................................................................................... 5 2.1 Choice of hardware platform ....................................................................................... 5 2.2 Choice of microprocessor ........................................................................................... 6 2.3 Choice of operating system ......................................................................................... 7 2.4 Choice of programming language ............................................................................... 8 2.5 Choice of compiler .................................................................................................... 10 2.6 Choice of function libraries ........................................................................................ 11 2.7 Choice of user interface framework ..........................................................................
    [Show full text]
  • SI 413, Unit 10: Control
    SI 413, Unit 10: Control Daniel S. Roche ([email protected]) Fall 2013 In our final unit, we will look at the big picture. First, within a program, the “big picture” means how the program flows from line to line during its execution. We’ll also see some of the coolest and most advanced features of modern languages. Then, for an even bigger picture, we’ll examine some of the legal issues and options involve with creating and sharing source code and programs. You will see some of the guiding principles of the open-source software movement, as well as a few unexpected consequences having to do with programming language implementations. 1 Control Flow We’ve talked about many different aspects of computer programs in some detail - functions, scopes, variables, types. But how does a running program move between these different elements? What features control the path of a program’s execution through the code? These features are what constitutes the control flow in a programming language, and different languages support different methods of control flow. The concept of control flow in very early computer languages, and in modern assembly languages, is termed “unstructured” programming and consists only of sequential execution and branches (i.e., goto statements). More modern programming languages feature the control structures that you have come to know and love: selection (if/else and switch statements), iteration (while, for, and for/each loops), and recursion (function calls). 1.1 Unstructured programming The most basic control flow method is so ingrained in our understanding of how programs work that you might not even notice it: Sequencing is the process by which control flows continually to the next instruction.
    [Show full text]