General-purpose GPUs have evolved to the point where they are also capable of very intense parallel numeric processing for a wide range of applications. However, programming these devices along with the on-chip CPU has been a hurdle. A new architectural concept for both hardware and software promises a smoother path to code development.
GEORGE KYRIAZIS, AMD
GPUs have transitioned in recent years from pure graphics accelerators to more general-purpose parallel processors, supported by standard APIs and tools such as OpenCL and DirectCompute. Those APIs are a promising start, but many hurdles remain for the creation of an environment that allows the GPU to be used as fluidly as the CPU for common programming tasks—for example, different memory spaces between CPU and GPU, non-virtualized hardware, and so on. The Heterogeneous System Architecture (HSA) removes those hurdles, and allows the programmer to take advantage of the parallel processor in the GPU as a peer or co-processor to the traditional multi-threaded CPU.
HSA provides a unified view of fundamental computing elements, allowing a programmer to write applications that seamlessly integrate CPUs with GPUs while benefiting from the best attributes of each. The essence of the HSA strategy is to create a single unified programming platform providing a strong foundation for the development of languages, frameworks and applications that exploit parallelism. More specifically, HSA aims to remove the CPU/GPU programmability barrier, reduce CPU/GPU communication latency, open the programming platform to a wider range of applications by enabling existing programming models, and create a basis for the inclusion of additional processing elements beyond the CPU and GPU.
HSA enables exploitation of the abundant data parallelism in the computational workloads of today and of the future in a power-efficient manner. It also provides continued support for traditional programming models and computer architectures.
HSA Compute Units and Architectural Features
The HSA architecture deals with two kinds of compute units. The first are CPUs, which can support both a native CPU instruction set and the HSA intermediate language (HSAIL) instruction set—more on HSAIL later. The second are GPUs, which support only the HSAIL instruction set. GPUs perform very efficient parallel execution.
An HSA application can run on a wide range of platforms consisting of both CPUs and GPUs. The HSA framework allows the application to execute at the best possible performance and power points on a given platform, without sacrificing flexibility. At the same time, HSA improves programmability, portability and compatibility. Prominent architectural features of HSA include:
Shared page table support: To simplify OS and user software, HSA allows a single set of page table entries to be shared between CPUs and GPUs. This allows units of both types to access memory through the same virtual address. The system is further simplified in that the operating system only needs to manage one set of page tables. This enables shared virtual memory (SVM) semantics between CPU and GPU.
Page faulting: Operating systems allow user processes to access more memory than is physically addressable by paging memory to and from disk. Early GPU hardware only allowed access to pinned memory, meaning that the driver invoked an OS call to prevent the memory from being paged out. In addition, the OS and driver had to create and manage a separate virtual address space for the GPU to use. HSA removes the burdens of pinned memory and separate virtual address management, by allowing compute units to page fault and to use the same large address space as the CPU.
User-level command queuing: Time spent waiting for OS kernel services was often a major performance bottleneck for throughput in previous computing systems. HSA substantially reduces the time to dispatch work to the GPU by providing a hardware dispatch queue per application and by allowing user mode processes to dispatch directly into those queues, requiring no OS kernel transitions or services. This makes the full performance of the platform available to the programmer, minimizing software driver overheads.
Hardware scheduling: HSA provides a mechanism whereby the GPU engine hardware can switch between application dispatch queues automatically, without requiring OS intervention on each switch. The OS scheduler is able to define every aspect of the switching sequence and still maintain control. Hardware scheduling is faster and consumes less power.
Coherent memory regions: In traditional GPU devices, even when the CPU and GPU are using the same system memory region, the GPU uses a separate address space from the CPU, and the graphics driver must flush and invalidate GPU caches at required intervals in order for the CPU and GPU to share results. HSA embraces a fully coherent shared memory model, with unified addressing. This provides programmers with the same coherent memory model that they enjoy on SMP CPU systems. It enables developers to write applications that closely couple CPU and GPU codes in popular design patterns like producer-consumer. The coherent memory heap is the default heap on HSA and is always present. Implementations may also provide a non-coherent heap for advanced programmers to request when they know there is no data sharing between processor types.
Figure 1 shows a simple HSA platform. The accelerated processing unit (APU) with HSA contains a multicore CPU, a GPU with multiple HSA compute units (H-CUs), and the HSA memory management unit (HMMU). These components communicate with coherent and non-coherent system memory.
The HAS platform. The HMMU provides a unified address space.
Programming Versatility and Hardware Compatibility
The HSA platform is designed to support high-level parallel programming languages and models, including C++ AMP, C++, C#, OpenCL, OpenMP, Java and Python, to name a few. HSA-aware tools generate program binaries that can execute on HSA-enabled systems supporting multiple instruction sets (typically, one for the CPU and one for the GPU), but also can run on existing architectures without HSA support.
Program binaries that can run on both CPUs and GPUs contain CPU instruction set architecture (ISA) code for the CPU and HSAIL code for the GPU. A finalizer converts HSAIL to GPU ISA. The finalizer is typically lightweight and may be run at install time, compile time, or program execution time, depending on choices made by the platform implementation.
Hardware/software interoperability is another important consideration when it comes to HSA versatility. HSA is a system architecture encompassing both software and hardware concepts. Hardware that supports HSA does not stand on its own, and similarly the HSA software stack requires HSA-compliant hardware to deliver the system’s capabilities.
While HSA requires certain functionality to be available in hardware, it also allows room for innovation. It enables a wide range of solutions that span both functionality—small vs. complex systems—and time in terms of backward and forward compatibility.
By standardizing the interface between the software stack and the hardware, HSA enables two dimensions of simultaneous innovation: Software developers can target a large hardware install base; and hardware vendors can differentiate core IP while maintaining compatibility with the existing and future software ecosystems (Figure 2).
The HSA software stack.
Optimizing for Parallel Workloads
General computing on GPUs has progressed in recent years from graphics shader-based programming to more modern APIs like DirectCompute and OpenCL. While this progression is definitely a step forward, the programmer still must explicitly copy data across address spaces, effectively treating the GPU as a remote processor.
Task programming APIs like Microsoft’s ConcRT, Intel’s Thread Building Blocks, and Apple’s Grand Central Dispatch are existing paradigms in parallel programming. They provide an easy-to-use task-based programming interface, but only on the CPU. Similarly, Thrust from NVIDIA provides a similar solution on the GPU.
HSA moves the programming bar further, enabling solutions for task-parallel and data-parallel workloads as well as for sequential workloads. Programs are implemented in a single programming environment and executed on systems containing both CPUs and GPUs.
HSA provides a programming interface containing queue and notification functions. This interface allows devices to access load-balancing and device-scaling facilities provided by the higher-level task queuing library. The overall goal is to allow developers to leverage both CPU and GPU devices by writing in task-parallel languages, like the ones they use today for multicore CPU systems. HSA’s goal is to enable existing task- and data-parallel languages and APIs and enable their natural evolution without requiring the programmer to learn a new HSA-specific programming language. The programmer is not tied to a single language, but rather has available a world of possibilities that can be leveraged from the ecosystem.
Unified Address Space
HSA defines a unified address space across CPU and GPU devices. HSA devices support virtual address translation: a pointer (that is, a virtual address) can be freely passed between devices, and shared page tables ensure that identical pointers resolve to the same physical address, and therefore the same data.
Internally, HSA implementations provide several special memory types with some on chip, some in caches, and some in system memory, but there is no need for special loads or stores. A GPU memory operation, including atomic operations, produces the same effects as a CPU operation using the same address.
All memory types are managed in hardware. An HSA-specific memory management unit (HMMU) supports the unified address space. The HMMU allows the GPUs to share page table mappings with the CPU. HSA supports unaligned accesses for loads and stores; however, atomic accesses have to be aligned to minimize hardware complexity.
Many compute problems today require much larger memory spaces than can be provided by traditional GPUs, whether we are discussing the local memory of a discrete GPU or the pinned system memory used by an APU. Partitioning a program to repeatedly use a small memory pool can require a huge programming effort, and for that reason large workloads often are not ported onto the GPU. By allowing the HSA throughput engine to use the same pageable virtual address space as the CPU, problems can be easily ported to an HSA system without special coding effort. This also helps to significantly increase computational performance of programs requiring very large data sets.
In addition, a unified address space allows data structures containing pointers (such as linked lists and various forms of tree and graph structures) to be freely used by both CPUs and GPUs. Today, such data structures require special handling by the programmer and often are the main reason why certain algorithms cannot be ported to a GPU. With HSA, this is handled transparently.
HSAIL and Workflow Efficiency
HSA exposes the parallel nature of GPUs through the HSA Intermediate Language (HSAIL). HSAIL is translated onto the underlying hardware’s instruction set architecture (ISA). While HSA GPUs are often embedded in powerful graphics engines, the HSAIL language is focused purely on compute and does not expose graphics-specific instructions in the base instruction set (HSAIL extensions may target additional accelerators in the future). The underlying hardware executes the translated ISA without awareness of HSAIL.
The smallest unit of execution in HSAIL is called a work-item. A work-item has its own set of registers, can access assorted system-generated values, and can access private (work-item local) memory. Work-items use regular loads and stores to access private memory, which resides in a special private data memory segment.
Work-items are organized into cooperating teamsz called work-groups. Work-groups can share data through group memory, again using normal loads and stores. Memory shared across a work-group is identified by address. Each work-item in a work-group has a unique identifier called its local ID. Each work-group executes on a single compute unit, and HSA provides special synchronization primitives for use within a work-group.
A work-group is part of a larger group called an n-dimensional range (NDRange). Each work-group in an NDRange has a unique work-group identifier called its global ID, available to any work-item within the NDRange. Work-items within an NDRange can communicate with the CPU through memory, because the address space (excluding group and private data) is shared across all work-items and is coherent with the CPU. Figure 3 shows an NDRange, a work-group and a work-item.
NDRange, work-group and work-item.
The finalizer translates HSAIL into the underlying hardware ISA at runtime. The finalizer also enforces HSA virtual machine semantics as part of the translation to ISA. Because of that, the underlying hardware architecture does not have to strictly adhere to the HSA Virtual Machine. The HSA Virtual Machine can also be implemented on a CPU, by having the finalizer convert HSAIL to the CPU’s ISA.
HSAIL has a unified memory view. The virtual address, rather than a special instruction encoding, determines whether a load or store address is private, shared among work-items in a work-group, or globally visible. This can relieve the programmer of much of the burden of memory management. Memory between the CPU and GPU cores is coherent. The HSA Memory Model is based on a relaxed consistency model and is consistent with the memory models defined for C++11, .NET and Java. Because the entire address space of the CPU is available to the GPU, the programmer can handle large data sets without special code to stream data into and out of the GPU.
The current state of GPU high-performance computing is not flexible enough for many of today’s computational problems. HSA helps meet this challenge by unifying CPUs and GPUs into a single system with common computing concepts, allowing the developer to solve a greater variety of complex problems more easily. This ultimately empowers software developers to easily innovate and unleash new levels of performance and functionality on modern computing devices, leading to powerful new experiences such as visually rich, intuitive, human-like interactivity.
The HSA Foundation (HSAF) was formed as an open industry standards body to unify the computing industry around this common approach. The foundation’s ultimate goal is to provide a unified install-base across all platforms and devices, which will simplify the software development process by enabling software developers to “write once and run everywhere.”
Advanced Micro Devices