Sometime in 2021, Aurora, the first planned U.S. exascale system, is scheduled to be fired up at Argonne National Laboratory. Cray (now HPE) and Intel are the key contractors. What will it take to create programs for Aurora and other exascale systems shortly thereafter? Last week Hal Finkel, ANL’s lead for compiler technology and programming languages, tackled this topic in his keynote at the virtual IWOCL/SYCLcon 2020.
As Finkel noted, “When I entered this field, a number of years ago, there was an ongoing debate as to whether the future of supercomputing would focus on manycore CPU-based architectures, or on architectures based on GPUs, or other kinds of computational accelerators. While the jury’s still out, in some sense, all of our upcoming systems will use GPUs. So they’ll be hot nodes, nodes with powerful CPUs that drive even more powerful GPUs.”
Heterogeneity, at least for now, is how we’ll attain exascale performance.
“It’s worth zooming in on the Aurora compute node for a moment,” said Finkel. “The GPUs are connected together using a low latency high bandwidth interconnect on node. In addition, the architecture features a unified memory subsystem, allowing memory to be addressed across both the CPU and the GPU. And this has important implications for our programming model. It means specifically and importantly that our program models will be able to focus on providing data motion capabilities for high performance use cases, while allowing the unified memory system subsystem to enable application data movement in cases where that enablement is important.”
Presented here are a handful of Finkel’s slides and comments (lightly edited and with apologies for any garbling). His hit list included parallelism, data mapping and transfer, legacy code (mostly Fortran) support, the tension between programmer freedom and compiler optimization, the rise of data parallel C++ (DPC++), Kokkos, Raja and SYCL, and much more. Finkel’s videotaped presentation and his slide deck are available at IWOCL website. It is a worthwhile, succinct overview.
Before plunging into Finkel’s comments and slides, here are his conclusions:
- Future supercomputers will continue to advance scientific progress in a variety of domains.
- Applications will rely on high-performance libraries as well as parallel-programming models.
- DPC++/SYCL will be a critical programming model on future HPC platforms.
- We will continue to understand the extent to which compiler optimizations assist the development of portably-performant applications vs. the ability to explicitly parameterize and dynamically compose the implementations of algorithms.
- Parallel programming models will continue to evolve: support for data layouts and less-host-centric models will be explored.
Finkel began with a quick refresher on what constitutes supercomputing.
“Traditional scientific supercomputing is computing for large, tightly coupled problems. Large is important. It implies in this case, both lots of computational capability, lots of flops, you could say, with lots of high performance memory. But tightly coupled is also important. It means that the computational density has to be high, because we need to connect all the different elements with a high bandwidth, low latency network. As a result, we end up with unique architectural challenges, getting that much compute with that high of a density,” said Finkel.
“There are common algorithmic classes. [For example] there’s dense linear algebra, sparse algebra, Fast Fourier transforms, particle methods, and so on. Some of these methods are used across many different domains. And it’s important to recognize that these different methods will stress the hardware in different ways. Some demand really high Flops rates or high computational ability, some demand really high performance from the memory subsystem more than anything else, and some demand high performance from the network more than anything else.”
“Here you can see our map of upcoming systems across a variety of different laboratories within the US Department of Energy’s computing ecosystem. Aurora is the system that we’re getting, and you can see it’s being provided by Intel, and Cray, but other vendors provide other systems that are an important part of our ecosystem. Importantly, it will be a machine that is powered by Intel CPUs and GPUs, will have a larger system memory, if they are interconnected, that is used to connect all the nodes together. In addition, it will have a state of the art file system that will provide unprecedented capacity and performance to our system,” he said.
“One thing that’s important to realize is that across the various pillars of applications that we serve – traditional simulation, data analytics, and large scale machine learning – all these applications sit on top of a set of high performance libraries, in addition to compilers, supported programming models, operating systems, workflow, schedulers, operating system kernel and so on. I want to highlight quickly that the inter-node program on all of these systems, the model that’s used in order to take advantage of that high-performance network is based on a program using MPI,” said Finkel.
“MPI – message passing interface – is the model of choice for doing the inter-node programming on large scale HPC systems. But that does not address the programming of the intra-node parallelism, and especially does not address the parallelism on GPUs. I should acknowledge that a large portion of our workload is still programmed in Fortran. It’s also true that most new code development seems have shifted to other languages, mainly C++, but also Python and a variety of other choices.”
“Intel, who is providing our system, has released something that they call the OneAPI, which covers program models and high performance libraries as well as the other interface. And that’s the primary target for programming Aurora. I mentioned that a lot of the applications depend not only on parallel programming models, but also on high-performance math libraries. Intel, of course, will provide high performance math libraries for our system, featuring some of the algorithms that were on the chart I showed you at the beginning, including things like Fourier transforms and dense linear algebra and so on. In addition, libraries will be provided to support data analytics and machine learning workloads,” said Finkel.
“There are a variety of programming models that we expect people to use on exascale systems. Not all these models will be supported on all the different systems however. On the other hand, some of these models are specifically designed to be portable across systems. And it’ll be interesting to explore the extent to which these various models are and are not portable, both syntactically and performance wise.
“One of the important models that we have on the systems is OpenMP, perhaps I’ll call it the second most important model. The applications that use OpenMP vary in base programming language. They could be C or C++ or Fortran. And as I noted, it’s important that we support Fortran, and OpenMP is the primary parallelization model supported by Fortran, whereas for C and C++ code, especially C++ code, there are more options.”
“Importantly, our system is going to support data parallel C++, which is the programming model that’s based on SYCL the standard from Khronos group. There are a number of different implementations of SYCL [and] it’s possible to run SYCL on a variety of today’s CPUs and also GPUs from Nvidia and AMD. DPC++ builds on top of SYCL and adds a number of features that are quite important are programming exascale supercomputers. This includes unified memory in addition to providing support for reductions on named lambdas, which is important for being able to wrap SYCL and DPC++ using higher level abstraction layers and subgroups for getting better performance on many systems,” said Finkel.
“Just to give you a point of comparison, here’s a simple example (slide below) using OpenMP to parallelize as a kernel and execute it on a GPU. You can see here that the OpenMP syntax is not extremely simple. If you know OpenMP, you may know that it’s easy on the CPU to parallelize a loop, but you require many additional syntax elements to get OpenMP to work on a GPU. This includes data mapping clauses to handle data motion, in addition to various kinds of parallelism decomposition for the GPU itself.”
“Here’s a corresponding kernel for SYCL. You can see here that there are a number of different objects that are created. There’s a work queue that is explicit in the code, in addition to the kernel that’s being executed, being passed as a lambda, a modern C++ feature, and the use of this accessor which allows a dynamic dependency graph to be constructed and the kernel to have execution and in addition data dependencies,” said Finkel.
“I want to talk about performance portability. I think this is an important topic especially as we talk about SYCL which is designed to be a performance portable parallel programming model for a variety of different architectures. I think it’s important to understand what our experience shows in the development of performance portable application. You might think that you develop an application the following way. First, you have a science problem, then you choose the algorithms you’re going to use to solve the problem. you implement and test the algorithms, you optimize the algorithms, and in the optimization process, take advantage of the knowledge of the architecture and tools. And then when you’re done, you have a high-performance code and you run it.
“However, that doesn’t generally work. The problem is that the freedom you have to optimize the algorithms and once they’re completely fixed, is generally not sufficient in order to solve the problem with the highest possible performance. There are various trade-offs that are made when taking an algorithm and implementation, including choices of basis functions and representations, regularization schemes and solver techniques.
“These are choices that cannot be made by a compiler, at least not a compiler is operating at a C++ or Fortran level. So it’s important to understand that while the creation of performance portable applications is certainly possible, it does mean those applications tend to be highly-parameterized so that those various algorithmic choices can be exposed and used as part of the tuning process,” said Finkel
Finkel emphasized it is important to recognize the way we offer applications is changing. “If we reach back to around 2015, five years ago, and we look at parallel programs we were using on our systems, you will see that most people were parallelizing for CPUs, and they were doing so using OpenMP directly. A much smaller percentage of people were using any kind of abstraction library,” said Finkel.
“This is changing. We are seeing even greater adoption of OpenMP, but many applications are not using OpenMP directly, and abstraction libraries are gaining in popularity. At the Department of Energy we developed at least two of these, and I’ll note two explicitly. One is Raja, and the other is called Kokkos. Both of these provide abstractions around parallel execution, including on GPUs. They make use of C++ lambdas and other modern C++ features in order to provide a productive programming experience. Also, they can use OpenMP or some other compiler directive-based scheme under the hood, but are probably using an underlying programming model for each system directly to implement the backend for that system, such as DPC++ or HIP or CUDA.
“Development of those models is also influencing the development of standard C++ itself. And in C++ 17 the standard library added parallel algorithms, which you can use much in the same way as you use the regular sequential standard algorithms, but now with the ability to specify the algorithm should be executed in parallel or vectorized,” he said.
“You might think that it should be the programmer’s responsibility to directly write code that is optimal across different architectures. To some extent programmers try to do this. But it’s important to realize there are constraints. Programmers use abstraction layers to manage development across large teams of programmers and they might not be able to write optimal code directly. And the codes that I want to run in parallel and that might benefit from running together might be in separate library components. There are various kinds of optimizations that a compiler might perform on parallel constructs. It might, for instance, want to split loops or fuse them together. It might want to do the same for kernels, splitting them apart or fusing them together in order to optimize for minimization of kernel launch overhead, or to minimize register pressure, and so on.
“The fact that programs, the flow of a program is broken up across different kernels and so on can interfere with compiler optimizations the compiler would otherwise perform. Having the compiler understand parallelism enough to get a better point aliasing results inside of our kernel, based on data from the code outside of the kernel, can yield significant benefit.
“In addition, it’s important to realize that the optimization of code and kernels is not simply limited to changing loop nest structures and so on. The data layout is [also] very important. The layout of data has a large effect on the structure of the kernel and the efficiency with which data can be accessed. And as you can see here (slide below), Kokkos, which is one of the C++ abstraction libraries I mentioned earlier, provides a way of customizing the data layout in an abstract, performance portable way. This is important. The performance that you can attain using the optimal data layout can be much, much greater than the performance of using a data layout that’s tuned perhaps for a different architecture.
There’s a good deal more to Finkel’s presentation. In concluding, he emphasized the importance of high performance libraries, abstraction, parameterization.
“[In] pushing the bounds of computing technology, applications are going to rely on high-performance libraries, as well as parallel programming models in order to attain high performance on the system. DPC++ is going to be a critical program model on future HPC systems. Especially on our upcoming system, Aurora,” he said
“We will continue to understand the extent to which compiler optimizations assists the development of portably performant applications versus in some sense, the ability to explicitly parameterize and dynamically compose the implementations of algorithms. there’s a trade-off there. The more freedom you give the programmer to explicitly choose how the program executes, the less freedom you give the compiler to change it, and vice versa. It’s a fundamental trade off in the design of programming languages and libraries. Parallel program models will continue to evolve to offer data layouts, and less host centric models will be explored in the future. And I expect we’ll see significant developments.”
At a minimum Finkel’s slide deck provides a fast look at programming development directions for the coming exascale beasts.
Link to Finkel’s keynote: https://www.youtube.com/watch?time_continue=1&v=oYWAJU-berw&feature=emb_logo
Link to Finkel’s keynote slides: https://www.iwocl.org/wp-content/uploads/iwocl-syclcon-2020-finkel-keynote-slides.pdf
IWOCL / SYCLcon 2020: https://www.iwocl.org/#