Compilers and More: A GPU and Accelerator Programming Model

By Michael Wolfe

December 9, 2008

Okay, maybe the title should be “Languages and More,” but I promise to talk about compilers further on below.

In recent columns, I’ve discussed parallel programming and programming GPUs and accelerators in particular. In May, I predicted that accelerator-based systems would dominate high performance computing, and suggested that an evolutionary approach to migrating applications from CPUs to accelerators was possible and appropriate. In September, I discussed in more detail the specifics of GPU hardware architecture, pointing out its strengths for high performance computing (lots of parallelism), as well as its weaknesses (limited to specific parallelism domains). In October, I showed what it takes to start porting a CPU program to a GPU, exposing some of the complexities of the interactions between the host and the GPU. The specific examples use NVIDIA’s very popular CUDA language, but I discuss OpenCL briefly as well (which should be about ready for public discussion about the time you read this). In my most recent column, I showed the details of optimizing a simple matmul kernel for a GPU, including testing various ways to organize it and vary the parallelism parameters.

If you read these, or are familiar with current approaches to programming accelerators, you are either discomforted by the complexities, or excited at the levels of control you can get. The low-level programming model in CUDA and OpenCL certainly has its place, though it’s not for the faint of heart. So, to go back to the first of those columns, can we come up with a different model of GPU and accelerator programming, one that retains most of the advantages of CUDA or OpenCL, but without requiring complete program rewrites, that can be applied to different target accelerators, and that retains the potential to develop and test in a more accessible environment? In short, a model that allows HPC programmers to focus on domain science instead of on computer science?

Architectural Model

Let’s start by looking at the features of the architecture that we want to use to advantage. Current GPUs are specific implementations of a programming model that works well for graphics problems. They support two levels of parallelism: an outer fully-parallel doall loop level, and an inner synchronous (SIMD or vector) loop level. Each level can be multidimensional (2 or 3 dimensions), but the domain must be strictly rectangular. The synchronous level may not be fully implemented with SIMD or vector operations, so explicit synchronization is supported (and required) across this level. No synchronization is supported between parallel threads across the doall level.

For those familiar with memory models, current GPUs implement a particularly weak model. In particular, they don’t support memory coherence between threads, unless those threads are parallel only at the synchronous level and the memory operations are separated by an explicit barrier. Otherwise, if one thread updates a memory location and another reads the same location, or two threads store a value to the same location, the hardware does not guarantee the results. You can’t say it gets the wrong answers, because such programs are defined as being in error. There is a software-managed cache on a GPU, and there are some hardware caches that can be used as well, but only in certain situations (and limited to read-only data).

The most significant characteristic is that the memory on the GPU or accelerator is separate from the host memory. The host can’t simply read or write to the accelerator memory because it’s not mapped into the virtual memory space of the host. Similarly, the accelerator can’t simply read or write to host memory; the host memory doesn’t support the bandwidth necessary for the accelerator, not to mention the need to support the virtual memory map on the accelerator.

The chips support parallelism on the order of hundreds of threads (today), but effective programs need parallelism on the order of thousands. This provides enough slack parallelism to tolerate long latency memory operations by thread switching, or multithreading, an idea pioneered by the venerable Denelcor HEP almost 30 years ago.

In summary, today’s GPUs look like an attached processor with its separate memory, that supports a multidimensional rectangular domain of parallelism, including doall and synchronous parallelism. We’d like a programming model that simplifies most of the hardware details, but gives experts finer levels of control. We probably can’t hide the distinction between the two levels of parallelism, but we’d like to avoid requiring the programmer to insert explicit synchronization as much as possible. It’s easy to map doall parallelism onto SIMD parallelism, but not the other way around, so we’d like to encourage programmers to program in a doall style when possible and appropriate. We probably can’t completely hide the distinction between host memory and accelerator memory, but the details of transferring data should be handled automatically.

But our programming model shouldn’t focus on the details of today’s GPUs as the ultimate accelerator architecture. One can envision accelerators with mostly (or only) synchronous parallelism (like the Clearspeed CSX700 accelerator processor), or with mostly doall parallelism (like the Tilera TILE64 chip). Future accelerators may share physical and/or virtual memory with the host, and may support a stronger memory model with richer synchronization methods. Software and hardware cache architectures are likely to change rapidly. A robust programming model should express parallelism broadly enough that compilers and tools can map an application onto future generations of accelerators as well as it does onto today’s GPUs. In fact, a successful model should be able to map applications onto a multicore X64 processor, where the SSE instructions implement the synchronous parallelism, and the doall parallelism is mapped across cores. From the available details, this model would even map well onto Intel’s proposed Larrabee chip. There will be work to tune the performance for each architecture, both in the tools and even at the application level, but the parallelism model needs to be reasonably portable.

Programming Model

How should we implement an accelerator-targeted programming model? Three options immediately come to mind: library, language, or directives. If you look at the array of parallel programming choices (all intended to make parallel programming easy), they span all three options.

Library-based solutions are attractive for many such problems; they are easy to port and can be independent of processor or compiler vendor. The MPI communication library for large system communication is one well-known example. It’s often easier to create (and modify) a standard for a library than for a language.

Language-based solutions expose the semantics in the language, allowing compilers or other tools to analyze and optimize the program. Co-Array Fortran, which is (currently) part of the next (allegedly minor) revision of the Fortran standard, exposes MPI-like parallelism and communication in the language, similar in some respects to Unified Parallel C (UPC). A compiler for Co-Array Fortran might be able to discover that a data copy from one image (thread) to another in a loop could be vectorized, given the appropriate support in the communication layer; such analysis in an MPI program is left entirely to the programmer. However, languages are expensive to implement, typically change quite slowly, and mistakes are hard to remedy once the standard is written.

A directive-based approach has some of the advantages of language-based solutions, in that directives expose the semantics to the compiler and other tools, allowing intelligent analysis and optimization. Such an approach also allows a program to be developed and tested on platforms that don’t support the directives, since the base language is unchanged. OpenMP is a widely available, successful parallel programming model based on directives to describe the parallel regions of the program.

Getting good performance on today’s accelerators depends on selecting a region that has enough work to amortize the overhead of moving data between the host and accelerator. This is one instance of the more general problem of selecting a region that has enough compute intensity to amortize the data traffic across the memory hierarchy, be it separate memory or multilevel caches. Some day, we may trust compilers to make this determination automatically, but not yet. So let me propose a model that borrows strategies from OpenMP, since I’m the PGI representative to the OpenMP group. I’ll propose directives in C and Fortran programs to delineate the regions of the program (loops) that should be accelerated (compiled for the GPU or other accelerator). Since the architecture model uses regular rectangular domains, I’ll propose using parallel loops as the primitive parallel operation.

The keys to tuning are minimizing and perhaps optimizing the data traffic between the host and accelerator, and selecting a schedule for the parallelism. In many cases, a compiler can analyze the nested loops and determine the input and output data sets, so it can manage the data traffic automatically. However, we should never trust automatic analysis to solve all our performance problems, so we’ll need directives or clauses to modify or augment the analysis.

As for scheduling, we saw in my previous column that there can be many possible schedules for even the simplest of parallel loops. Recent academic research in this area depends on doing more or less what I did by hand: generating many versions of the program and running each of them, then choosing the best one from the bunch; see Shane Ryoo’s PhD dissertation (University of Illinois, 2008), and joint work from Professors Ramanujam and Sadayappan (Louisiana State University and The Ohio State University) as good examples. Such an approach is valid for research, or when searching for a good algorithm for a highly tuned library, but inappropriate for a compiler. Instead, we will depend on the compiler to determine a reasonably good schedule (as we do when we use automatic parallelization and vectorization today), again with directives or clauses to modify or augment the decisions.

It’s important that a programmer be able to control any compiler optimization decision here; the difference between good and bad performance is quite dramatic, and at least in the immediate future, any compiler decision will be made with only partial information. However, to support this requires that the compiler tell the programmer what decisions it has made, and hopefully why, so the programmer knows whether it’s appropriate to step in and make a change.

So let me propose two directives. The first delineates an accelerator region, with optional clauses to control the data movement between host and accelerator memory. Borrowing liberally from OpenMP, I’ll propose a #pragma acc prefix for C directives, and !$acc prefix in Fortran. In C, I’ll describe an acceleration region as:

    #pragma acc region     {        /* loops to be accelerated go here */     } 

Fortran doesn’t have structured blocks (yet), so we’ll use region and end region directives:

   !$acc region        ! loops to be accelerated go here    !$acc end region 

Compare these to the OpenMP parallel regions. I propose optional clauses to tell the compiler what data needs to be copied into the region, from host to accelerator, what data needs to be copied out, and what data is local to the region; local data corresponds roughly to OpenMP private data. Compiler analysis is often able to determine the in/out/local data automatically.

The second directive is used to describe the mapping of parallel loops onto the hardware parallelism, what I called the schedule earlier. This corresponds roughly to the OpenMP loop directive, which describes the work-sharing pattern of parallel loops. It’s probably easiest to explain with a familiar example; in my most recent column, I showed several versions of matmul in CUDA with different schedules. The first (and simplest) version would be written (in Fortran) using these directives as:

   !$acc region       !$acc do parallel       do j = 1, m         do k = 1, p           !$acc do parallel, vector(32)           do i = 1, n             a(i,j) = a(i,j) + b(i,k)*c(k,j)           enddo         enddo       enddo    !$acc end region 

The loop directives do two things: the first is to tell the compiler about loop-level parallelism, augmenting its analysis. The second is to tell the compiler how to schedule or map the loop-level parallelism onto the hardware. In this loop, both the i and j loops exhibit doall parallelism, but we want to map the stride-1 i loop onto the synchronous (vector) parallelism in strips of size 32, using doall parallelism between the strips. We expect compilers to issue a warning message if a programmer inserts a do parallel directive on a loop that compiler analysis shows is in fact not parallel. Compare this code for clarity with the actual CUDA kernel.

This isn’t intended to be a user guide, tutorial, even a formal proposal, but I hope to convince you that a directive-based approach is feasible in the short term, and can address many of the problems programmers will face when porting large applications for use on host+GPU platforms in particular, and host+accelerators in general.

This model does use reasonably sophisticated compiler analysis, but nothing that hasn’t been implemented in commercial parallelizing compilers for many years. In this example, the compiler must take the following steps:

  • Determine what data is input to the region; for this loop, the input data is a(1:n,1:m), b(1:n,1:p), c(1:p,1:m), and the loop limits.
  • Determine what data is output to the region; this is simply a(1:n,1:m).
  • Determine what data is local to the region, which is empty (except perhaps for the loop counters). Classical data flow and array region analysis solves all three of these problems.
  • Determine which loops can run in parallel, augmented by information in the directives. For this loop, the j and i loops are completely parallel; the k loop requires a sum reduction, which is less efficient but could still be parallelized.
  • Determine the loop schedule; in this example, the schedule is specified by the directives. Without the loop directives, the compiler would have to search among the possible schedules and select a best one; note to academics: this is still a fertile area for continued research.
  • Generate code for the accelerator. For the most part, this is a classical compiler problem, and well known methods apply. On a target like the NVIDIA GPU, optimizing for the software-managed cache adds some complexity, but such problems have been addressed on past machines as well.
  • Generate host code to move data to the accelerator, launch the accelerator kernel(s), and move results back from the accelerator.

Final Words

Will adoption and use of directives such as these make GPUs more generally applicable? These directives may make GPUs more accessible, but there are still serious limitations to the parallelism GPUs support. The restrictions include rectangular domains, two levels of parallelism, limited synchronization, and a weak memory model (in the formal sense). This makes it unlikely that anyone will be porting unstructured mesh code or dynamic pointer-chasing data structures to a GPU anytime soon.

Can this programming model be adapted to make parallel programming easy in general? I’ve argued that parallel programming is difficult, and always will be, regardless of the programming model, and I’m not backing down. To reiterate, this directive model is intended to make accelerator programming accessible, so programmers can focus on algorithms and performance, not on syntax and other trivialities.

This proposed style of parallel programming isn’t universal, but it does address a significant segment of the parallel community. The model is portable, across GPUs, across accelerators, even to multicore CPUs, though we need to develop the compilers. Moreover, it’s nicely incremental; you can use these directives to accelerate parts of your program without having to undertake a whole rewrite, and, as with OpenMP, you can still build and test your application on the host by ignoring the directives altogether.

—–

Michael Wolfe has developed compilers for over 30 years in both academia and industry, and is now a senior compiler engineer at The Portland Group, Inc. (www.pgroup.com), a wholly-owned subsidiary of STMicroelectronics, Inc. The opinions stated here are those of the author, and do not represent opinions of The Portland Group, Inc. or STMicroelectronics, Inc.

—–

UPDATE: This article was original published during our SC08 coverage on November 20. Due to recent developments in heterogeneous compilers by PGI and CAPS Enterprise, as well as the ratification of the OpenCL standard, we felt it was worth another look. — Editor

Subscribe to HPCwire's Weekly Update!

Be the most informed person in the room! Stay ahead of the tech trends with industy updates delivered to you every week!

Activist Investor Starboard Buys 10.7% Stake in Mellanox; Sale Possible?

November 20, 2017

Starboard Value has reportedly taken a 10.7 percent stake in interconnect specialist Mellanox Technologies, and according to the Wall Street Journal, has urged the company “to improve its margins and stock and explore Read more…

By John Russell

Installation of Sierra Supercomputer Steams Along at LLNL

November 20, 2017

Sierra, the 125 petaflops (peak) machine based on IBM’s Power9 chip being built at Lawrence Livermore National Laboratory, sometimes takes a back seat to Summit, the ~200 petaflops system being built at Oak Ridge Natio Read more…

By John Russell

SC Bids Farewell to Denver, Heads to Dallas for 30th

November 17, 2017

After a jam-packed four-day expo and intensive six-day technical program, SC17 has wrapped up another successful event that brought together nearly 13,000 visitors to the Colorado Convention Center in Denver for the larg Read more…

By Tiffany Trader

HPE Extreme Performance Solutions

Harness Scalable Petabyte Storage with HPE Apollo 4510 and HPE StoreEver

As a growing number of connected devices challenges IT departments to rapidly collect, manage, and store troves of data, organizations must adopt a new generation of IT to help them operate quickly and intelligently. Read more…

SC17 Keynote – HPC Powers SKA Efforts to Peer Deep into the Cosmos

November 17, 2017

This week’s SC17 keynote – Life, the Universe and Computing: The Story of the SKA Telescope – was a powerful pitch for the potential of Big Science projects that also showcased the foundational role of high performance computing in modern science. It was also visually stunning. Read more…

By John Russell

SC Bids Farewell to Denver, Heads to Dallas for 30th

November 17, 2017

After a jam-packed four-day expo and intensive six-day technical program, SC17 has wrapped up another successful event that brought together nearly 13,000 visit Read more…

By Tiffany Trader

SC17 Keynote – HPC Powers SKA Efforts to Peer Deep into the Cosmos

November 17, 2017

This week’s SC17 keynote – Life, the Universe and Computing: The Story of the SKA Telescope – was a powerful pitch for the potential of Big Science projects that also showcased the foundational role of high performance computing in modern science. It was also visually stunning. Read more…

By John Russell

How Cities Use HPC at the Edge to Get Smarter

November 17, 2017

Cities are sensoring up, collecting vast troves of data that they’re running through predictive models and using the insights to solve problems that, in some Read more…

By Doug Black

Student Cluster LINPACK Record Shattered! More LINs Packed Than Ever before!

November 16, 2017

Nanyang Technological University, the pride of Singapore, utterly destroyed the Student Cluster Competition LINPACK record by posting a score of 51.77 TFlop/s a Read more…

By Dan Olds

Hyperion Market Update: ‘Decent’ Growth Led by HPE; AI Transparency a Risk Issue

November 15, 2017

The HPC market update from Hyperion Research (formerly IDC) at the annual SC conference is a business and social “must,” and this year’s presentation at S Read more…

By Doug Black

Nvidia Focuses Its Cloud Containers on HPC Applications

November 14, 2017

Having migrated its top-of-the-line datacenter GPU to the largest cloud vendors, Nvidia is touting its Volta architecture for a range of scientific computing ta Read more…

By George Leopold

HPE Launches ARM-based Apollo System for HPC, AI

November 14, 2017

HPE doubled down on its memory-driven computing vision while expanding its processor portfolio with the announcement yesterday of the company’s first ARM-base Read more…

By Doug Black

OpenACC Shines in Global Climate/Weather Codes

November 14, 2017

OpenACC, the directive-based parallel programming model used mostly for porting codes to GPUs for use on heterogeneous systems, came to SC17 touting impressive Read more…

By John Russell

US Coalesces Plans for First Exascale Supercomputer: Aurora in 2021

September 27, 2017

At the Advanced Scientific Computing Advisory Committee (ASCAC) meeting, in Arlington, Va., yesterday (Sept. 26), it was revealed that the "Aurora" supercompute Read more…

By Tiffany Trader

NERSC Scales Scientific Deep Learning to 15 Petaflops

August 28, 2017

A collaborative effort between Intel, NERSC and Stanford has delivered the first 15-petaflops deep learning software running on HPC platforms and is, according Read more…

By Rob Farber

Oracle Layoffs Reportedly Hit SPARC and Solaris Hard

September 7, 2017

Oracle’s latest layoffs have many wondering if this is the end of the line for the SPARC processor and Solaris OS development. As reported by multiple sources Read more…

By John Russell

AMD Showcases Growing Portfolio of EPYC and Radeon-based Systems at SC17

November 13, 2017

AMD’s charge back into HPC and the datacenter is on full display at SC17. Having launched the EPYC processor line in June along with its MI25 GPU the focus he Read more…

By John Russell

Nvidia Responds to Google TPU Benchmarking

April 10, 2017

Nvidia highlights strengths of its newest GPU silicon in response to Google's report on the performance and energy advantages of its custom tensor processor. Read more…

By Tiffany Trader

Google Releases Deeplearn.js to Further Democratize Machine Learning

August 17, 2017

Spreading the use of machine learning tools is one of the goals of Google’s PAIR (People + AI Research) initiative, which was introduced in early July. Last w Read more…

By John Russell

GlobalFoundries Puts Wind in AMD’s Sails with 12nm FinFET

September 24, 2017

From its annual tech conference last week (Sept. 20), where GlobalFoundries welcomed more than 600 semiconductor professionals (reaching the Santa Clara venue Read more…

By Tiffany Trader

Amazon Debuts New AMD-based GPU Instances for Graphics Acceleration

September 12, 2017

Last week Amazon Web Services (AWS) streaming service, AppStream 2.0, introduced a new GPU instance called Graphics Design intended to accelerate graphics. The Read more…

By John Russell

Leading Solution Providers

EU Funds 20 Million Euro ARM+FPGA Exascale Project

September 7, 2017

At the Barcelona Supercomputer Centre on Wednesday (Sept. 6), 16 partners gathered to launch the EuroEXA project, which invests €20 million over three-and-a-half years into exascale-focused research and development. Led by the Horizon 2020 program, EuroEXA picks up the banner of a triad of partner projects — ExaNeSt, EcoScale and ExaNoDe — building on their work... Read more…

By Tiffany Trader

Delays, Smoke, Records & Markets – A Candid Conversation with Cray CEO Peter Ungaro

October 5, 2017

Earlier this month, Tom Tabor, publisher of HPCwire and I had a very personal conversation with Cray CEO Peter Ungaro. Cray has been on something of a Cinderell Read more…

By Tiffany Trader & Tom Tabor

Reinders: “AVX-512 May Be a Hidden Gem” in Intel Xeon Scalable Processors

June 29, 2017

Imagine if we could use vector processing on something other than just floating point problems.  Today, GPUs and CPUs work tirelessly to accelerate algorithms Read more…

By James Reinders

Cray Moves to Acquire the Seagate ClusterStor Line

July 28, 2017

This week Cray announced that it is picking up Seagate's ClusterStor HPC storage array business for an undisclosed sum. "In short we're effectively transitioning the bulk of the ClusterStor product line to Cray," said CEO Peter Ungaro. Read more…

By Tiffany Trader

Intel Launches Software Tools to Ease FPGA Programming

September 5, 2017

Field Programmable Gate Arrays (FPGAs) have a reputation for being difficult to program, requiring expertise in specialty languages, like Verilog or VHDL. Easin Read more…

By Tiffany Trader

HPC Chips – A Veritable Smorgasbord?

October 10, 2017

For the first time since AMD's ill-fated launch of Bulldozer the answer to the question, 'Which CPU will be in my next HPC system?' doesn't have to be 'Whichever variety of Intel Xeon E5 they are selling when we procure'. Read more…

By Dairsie Latimer

Flipping the Flops and Reading the Top500 Tea Leaves

November 13, 2017

The 50th edition of the Top500 list, the biannual publication of the world’s fastest supercomputers based on public Linpack benchmarking results, was released Read more…

By Tiffany Trader

IBM Advances Web-based Quantum Programming

September 5, 2017

IBM Research is pairing its Jupyter-based Data Science Experience notebook environment with its cloud-based quantum computer, IBM Q, in hopes of encouraging a new class of entrepreneurial user to solve intractable problems that even exceed the capabilities of the best AI systems. Read more…

By Alex Woodie

Share This