Memory concept. Grid concept, Synchronization. GPU Programming. Szénási Sándor.

Similar documents
CS 179: GPU Computing. Lecture 2: The Basics

Atomic Operations. Atomic operations, fast reduction. GPU Programming. Szénási Sándor.

CUDA GPGPU Workshop CUDA/GPGPU Arch&Prog

ECE 574 Cluster Computing Lecture 15

An Introduction to GPGPU Pro g ra m m ing - CUDA Arc hitec ture

Introduction to CUDA CME343 / ME May James Balfour [ NVIDIA Research

Pinned-Memory. Table of Contents. Streams Learning CUDA to Solve Scientific Problems. Objectives. Technical Issues Stream. Pinned-memory.

Fundamental Optimizations in CUDA Peng Wang, Developer Technology, NVIDIA

Lecture 9. Outline. CUDA : a General-Purpose Parallel Computing Architecture. CUDA Device and Threads CUDA. CUDA Architecture CUDA (I)

Introduction to CUDA C

CUDA Programming. Week 1. Basic Programming Concepts Materials are copied from the reference list

CUDA Performance Optimization. Patrick Legresley

Register file. A single large register file (ex. 16K registers) is partitioned among the threads of the dispatched blocks.

ECE 574 Cluster Computing Lecture 17

CUDA Workshop. High Performance GPU computing EXEBIT Karthikeyan

CS179 GPU Programming Recitation 4: CUDA Particles

Introduction to CUDA C

CS179 GPU Programming: CUDA Memory. Lecture originally by Luke Durant and Tamas Szalay

Tesla Architecture, CUDA and Optimization Strategies

CUDA Lecture 2. Manfred Liebmann. Technische Universität München Chair of Optimal Control Center for Mathematical Sciences, M17

CUDA PROGRAMMING MODEL. Carlo Nardone Sr. Solution Architect, NVIDIA EMEA

GPU Programming Using CUDA

Programming with CUDA, WS09

CUDA. Schedule API. Language extensions. nvcc. Function type qualifiers (1) CUDA compiler to handle the standard C extensions.

GPU Programming Using CUDA. Samuli Laine NVIDIA Research

Parallel Numerical Algorithms

Fundamental CUDA Optimization. NVIDIA Corporation

CUDA Memories. Introduction 5/4/11

GPU Programming Using CUDA. Samuli Laine NVIDIA Research

Introduction to GPGPUs and to CUDA programming model

CUDA OPTIMIZATIONS ISC 2011 Tutorial

Outline 2011/10/8. Memory Management. Kernels. Matrix multiplication. CIS 565 Fall 2011 Qing Sun

GPU Computing Workshop CSU Getting Started. Garland Durham Quantos Analytics

University of Bielefeld

Fundamental CUDA Optimization. NVIDIA Corporation

Introduction to Parallel Computing with CUDA. Oswald Haan

Device Memories and Matrix Multiplication

Massively Parallel Algorithms

Matrix Multiplication in CUDA. A case study

This is a draft chapter from an upcoming CUDA textbook by David Kirk from NVIDIA and Prof. Wen-mei Hwu from UIUC.

An Introduction to GPU Computing and CUDA Architecture

CUDA Memory Types All material not from online sources/textbook copyright Travis Desell, 2012

Parallel Programming and Debugging with CUDA C. Geoff Gerfin Sr. System Software Engineer

Parallel Computing. Lecture 19: CUDA - I

CUDA C/C++ BASICS. NVIDIA Corporation

COMP 322: Fundamentals of Parallel Programming. Flynn s Taxonomy for Parallel Computers

Lecture 3: Introduction to CUDA

GPU Programming. Lecture 2: CUDA C Basics. Miaoqing Huang University of Arkansas 1 / 34

CUDA Optimizations WS Intelligent Robotics Seminar. Universität Hamburg WS Intelligent Robotics Seminar Praveen Kulkarni

Massively Parallel Architectures

Introduction to CUDA Programming

Kernel optimizations Launch configuration Global memory throughput Shared memory access Instruction throughput / control flow

CUDA C Programming Mark Harris NVIDIA Corporation

GPU Programming. Alan Gray, James Perry EPCC The University of Edinburgh

CUDA Exercises. CUDA Programming Model Lukas Cavigelli ETZ E 9 / ETZ D Integrated Systems Laboratory

Introduction to GPU programming. Introduction to GPU programming p. 1/17

Zero-copy. Table of Contents. Multi-GPU Learning CUDA to Solve Scientific Problems. Objectives. Technical Issues Zero-copy. Multigpu.

Review. Lecture 10. Today s Outline. Review. 03b.cu. 03?.cu CUDA (II) Matrix addition CUDA-C API

04. CUDA Data Transfer

Fundamental Optimizations

Supercomputing, Tutorial S03 New Orleans, Nov 14, 2010

Hardware/Software Co-Design

Lecture 15: Introduction to GPU programming. Lecture 15: Introduction to GPU programming p. 1

Basic Elements of CUDA Algoritmi e Calcolo Parallelo. Daniele Loiacono

Information Coding / Computer Graphics, ISY, LiTH. Introduction to CUDA. Ingemar Ragnemalm Information Coding, ISY

Introduc)on to GPU Programming

CUDA Performance Considerations (2 of 2) Varun Sampath Original Slides by Patrick Cozzi University of Pennsylvania CIS Spring 2012

Writing and compiling a CUDA code

Learn CUDA in an Afternoon. Alan Gray EPCC The University of Edinburgh

CUDA C/C++ BASICS. NVIDIA Corporation

HPCSE II. GPU programming and CUDA

Scientific discovery, analysis and prediction made possible through high performance computing.

Zero Copy Memory and Multiple GPUs

Stanford University. NVIDIA Tesla M2090. NVIDIA GeForce GTX 690

Vector Addition on the Device: main()

CUDA Programming (Basics, Cuda Threads, Atomics) Ezio Bartocci

Advanced CUDA Programming. Dr. Timo Stich

Introduction to GPU Computing Junjie Lai, NVIDIA Corporation

Introduction to CUDA (1 of n*)

EEM528 GPU COMPUTING

CUDA Performance Optimization Mark Harris NVIDIA Corporation

CUDA Memory Hierarchy

COSC 6374 Parallel Computations Introduction to CUDA

CUDA Memory Model. N. Cardoso & P. Bicudo. Física Computacional (FC5)

GPU CUDA Programming

High-Performance Computing Using GPUs

COSC 462 Parallel Programming

GPU & High Performance Computing (by NVIDIA) CUDA. Compute Unified Device Architecture Florian Schornbaum

GPU Computing with CUDA

Introduction to CUDA 5.0

GPU Memory Memory issue for CUDA programming

Speed Up Your Codes Using GPU

Memory. Lecture 2: different memory and variable types. Memory Hierarchy. CPU Memory Hierarchy. Main memory

Parallel Programming Principle and Practice. Lecture 9 Introduction to GPGPUs and CUDA Programming Model

Advanced Topics: Streams, Multi-GPU, Tools, Libraries, etc.

Lecture 2: Introduction to CUDA C

GPU Computing: Introduction to CUDA. Dr Paul Richmond

Information Coding / Computer Graphics, ISY, LiTH. Introduction to CUDA. Ingemar Ragnemalm Information Coding, ISY

Module 2: Introduction to CUDA C

CUDA C/C++ Basics GTC 2012 Justin Luitjens, NVIDIA Corporation

Transcription:

Memory concept Grid concept, Synchronization GPU Programming http://cuda.nik.uni-obuda.hu Szénási Sándor szenasi.sandor@nik.uni-obuda.hu GPU Education Center of Óbuda University

MEMORY CONCEPT Off-chip memory Dynamic allocation On-chip memory Tiled matrix multiplication

Inside one CUDA device Memory overview This figure illustrates the CUDA hardware model for a device Every device contains one or more multiprocessors, and these multiprocessors contains one or (more frequently) more SIMT execution units Inside one multiprocessor SIMT execution units Registers Shared memory (available for all threads) Read-only constant and texture cache 3

The memory concept From the developer s perspective Thread level Private registers (R/W) Local memory (R/W) Block level Shared memory (R/W) Constant memory (R) Grid level Global memory (R/W) Texture memory (R) Device-host communication The global, constant and texture memory spaces can be read from or written to by the CPU and are persistent across kernel launches by the same application 4

Global memory Details Has the lifetime of the application Accessible for all blocks/threads Accessible for the host Readable/writeable Large Quite slow Static declaration Use the device keyword Example device float *devptr; device float devptr[1024]; 5

CUDA memory model constant memory Details Has the lifetime of the application Accessible for all blocks/threads Accessible for the host Readable/writeable for the host Readable for the device Cached Statuc declaration Use the constant keyword Example: constant float *devptr; constant float devptr[1024]; 6

Copy to static device variable (global or constant) From host to device Function name: cudamemcpytosymbol Parameters symbol - Symbol destination on device (host or device) src - Source memory address count - Size in bytes to copy offset - Offset from start of symbol in bytes kind - Type of transfer Copies count bytes from the memory area pointed to by src to the memory area pointed to by offset bytes from the start of symbol symbol. Symbol can either be a variable that resides in global or constant memory space, or it can be a character string, naming a variable that resides in global or constant memory space Asynchronous version: cudamemcpytosymbolasync From device to device The kind parameter can be cudamemcpyhosttodevice cudamemcpydevicetodevice. 7

Copy from static device variable (global or constant) From device to host Function name: cudamemcpyfromsymbol Parameters dst - Destination memory address (host or device) symbol - Symbol source from device count - Size in bytes to copy offset - Offset from start of symbol in bytes kind - Type of transfer Copies count bytes from the memory area pointed to by offset bytes from the start of symbol symbol to the memory area pointed to by dst. Symbol can either be a variable that resides in global or constant memory space, or it can be a character string, naming a variable that resides in global or constant memory space Asynchronous version: cudamemcpyfromsymbolasync From device to device The kind parameter can be cudamemcpyhosttodevice cudamemcpydevicetodevice. 8

Get pointer for static device variables To acquire a pointer to a static variable Function name: cudagetsymboladdress Parameters devptr - Return device pointer associated with symbol symbol - Global variable or string symbol to search for Returns in *devptr the address of symbol symbol on the device. symbol can either be a variable that resides in global or constant memory space, or it can be a character string, naming a variable that resides in global or constant memory space. Example constant float dev_a[100]; float *dev_a_ptr; cudagetsymboladdress((void**)&dev_a_ptr, dev_a); Get the size of a static device variable Function name: cudagetsymbolsize Parameters size - Size of object associated with symbol symbol - Global variable or string symbol to find size of 9

CUDA memory model texture memory Details Has the lifetime of the application Accessible for all blocks/threads Accessible for the host Readable/writeable for the host Readable for the device Available for image manipulating functions (texturing etc.). Not a common byte based array. Declaration We do not discuss 10

MEMORY CONCEPT Off-chip memory Dynamic allocation On-chip memory Tiled matrix multiplication

Memory handling Static allocation Variabled declared as usual in C languages The declaration contains one of the previously introduced keywords ( device, constant etc.) The variable is accessible as usual in C languages, we can use them as operands and function parameters etc. Dynamic allocation The CUDA class library have several memory handling functions. With these function we can allocate memory copy memory free memory The memory is accessible via pointers Pointer usage is the same as common in C languages but it is important to note that the device has a separated address space (device and host memory pointers are exchangeable) 12

Dynamic allocation allocate and free memory Allocate device memory Function name: cudamalloc Parameters devptr - Pointer to allocated device memory size - Requested allocation size in bytes Allocates size bytes of linear memory on the device and returns in *devptr a pointer to the allocated memory. The allocated memory is suitably aligned for any kind of variable. The memory is not cleared Example float *dev_ptr; cudamalloc((void**)&dev_ptr, 256 * sizeof(float)); Warning: host memory and device memory have separate address spaces. It s the programmers responsibility to use them in the right context Free device memory Function name: cudafree Parameters devptr - Pointer to allocated device memory Example cudafree(dev_ptr); 13

Transfer in device memory Copy between memory regions Function name: cudamemcpy For asynchronous copy: cudamemcpyasync Parameters dst - Destination memory address src - Source memory address count - Size in bytes to copy kind - Direction of transfer Copies count bytes from the memory area pointed to by src to the memory area pointed to by dst Valid values for direction host host (cudamemcpyhosttohost) host device (cudamemcpyhosttodevice) device host (cudamemcpydevicetohost) device device (cudamemcpydevicetodevice) Example float *hostptr =...; float *devptr =...; cudamemcpy(devptr, hostptr, 256 * sizeof(float), cudamemcpyhosttodevice); 14

Pinned memory Pinned memory In the host side we can allocate pinned memory. This memory object is always stored in the physical memory, therefore the GPU can fetch it without the help of the CPU Non-pinned memory can stored in swap (in practice in the hard drive) therefore it can cause page faults on access. So the driver needs to check every access To use asynchronous memory transfers the memory must be allocated by the special CUDA functions (instead of standard C malloc function): cudahostalloc() cudafreehost() It has several benefits: copies between pinned memory and device memory can be performed concurrently with kernel execution for some devices pinned memory can be mapped to the address space of the device on some GPUs on systems with a front-side bus, bandwidth of memory transfer is higher in case of using pinned memory in the host Obviously the OS can not allocate as many page-locked memory as pageable. And the using of too much page-locked memory can decrease the overall system performance 15

Zero-copy memory Zero copy memory A special version of the pinned memory is the zero-copy memory. In this case we don t need to transfer data from host to the device, the kernel can directly access the host memory Also called mapped memory because in this case the this memory region is mapped into the CUDA address space Useful when the GPU has no memory and uses the system RAM the host side wants to access to data while kernel is still running the data does not fit into GPU memory we want to execute enough calculation to hide the memory transfer latency Mapped memory is shared between host and device therefore the application must synchronize memory access using streams or events The CUDA device properties structures has information the capabilities of the GPU: canmaphostmemory = 1 if the mapping feature is available Portable pinned memory Pinned memory allowed to move between host threads (in case of multi-gpu environments) 16

Additional memory handling functions Get free memory Function name: cudamemgetinfo Parameters free - Returned free memory in bytes total - Returned total memory in bytes Returns in *free and *total respectively, the free and total amount of memory available for allocation by the device in bytes Set memory region Function name: cudamemset Asynchronous function: cudamemsetasync Parameters devptr - Pointer to device memory value - Value to set for each byte of specified memory count - Size in bytes to set Initializes or sets device memory to a value 17

MEMORY CONCEPT Off-chip memory Dynamic allocation On-chip memory Tiled matrix multiplication

CUDA memory model - registers Details Has the lifetime of the thread Accessible for only the owner thread Not accessible for the host/other threads Readable/writeable Quite fast Limited number of registers Not dedicated registers, the GPU have a fixed size register set Declaration Default storing area for local variables Example global void kernel { int regvar; } Notes The compiler gives information about the number of used registers Compiler parameters can limit the maximum number of registers 19

CUDA memory model local memory Details Has the lifetime of the thread Accessible for only the owner thread Not accessible for the host/other threads Readable/writeable Quite slow Declaration Looks like a normal register, but these variables are stored in the global memory If there aren t any space for registers, the compiler will automatically create the variables in local memory Example global void kernel { int regvar; } Notes Arrays are stored in the local memory by default 20

Shared memory Shared memory Has the lifetime of the block Accessible for all threads in this block Not accessible for the host Readable/writeable for threads Quite fast Size is strongly limited (see kernel start) Static declaration Use the shared keyword Example shared float a; global void kernel { shared float devptr[1024]; } Easy way, when the amount of required memory is already known at compile time 21

Shared memory dynamic allocation Runtime allocation of shared memory The third kernel launch parameter is the size of the required shared memory Every block will have an array in the shared memory with the given size This array can be referenced by an unsized extern array Only a low level access is available in this case extern shared float s[]; global void Kernel { s[threadidx.x] = dev_a[threadidx.x] } The 3 rd execution configuration parameter is the allocated shared memory size per thread blocks (in bytes) Kernel<<<10, 20, 20 * sizeof(float)>>>( ) In the case of multiple arrays, we can use the following syntax extern shared int s[]; int *integerdata = s; float *floatdata = (float*)&integerdata[ni]; char *chardata = (char*)&floatdata[nf]; Kernel<<<10, 20, ni*sizeof(int) + nf*sizeof(float) + nc*sizeof(char) >>>( ) 22

Cache and shared memory configuration Configurable cache control The on-chip memory can be partitioned between L1 cache and shared memory using 3 ( CC2.0) or 2 ( CC3.0) options Set cache configuration Function name: cudafuncsetcacheconfig Parameters func - Device function symbol cacheconfig - Requested cache configuration Possible cache configurations cudafunccacheprefernone no preference for shared memory or L1 (default) cudafunccacheprefershared prefer larger shared memory and smaller L1 cache cudafunccachepreferl1 prefer larger L1 cache and smaller shared memory cudafunccachepreferequal prefer equal size L1 cache and shared memory Sets through cacheconfig the preferred cache configuration for the function specified via func. This is only a preference Similar function to configure the device: cudadevicesetcacheconfig 23

Physical implementation of the CUDA memory model Dedicated hardware memory The compiler will map here the registers, shared memory ~1 cycle Device Multiprocessor N Multiprocessor 2 Multiprocessor 1 Device memory without cache Shared Memory The compiler will map here the local variables, global memory Registers Processor 1 Registers Processor 2 Registers Processor M Instruction Unit ~100 cycle Device memory with cache The compiler will map here the constant memory, texture memory, instruction cache ~1-10-100 cycle Device memory Constant Cache Texture Cache 24

CUDA memory regions Grouped by visibility Global memory Constant memory Texture memory Shared memory Registers Local memory Grouped by accessibility Global Constant Texture Shared Registers Local memory Host Dynamic allocation Dynamic allocation Dynamic allocation - R/W R/W - - Eszköz - Static allocation Static allocation Static allocation R/W R R/W R/W 25

MEMORY CONCEPT Off-chip memory Dynamic allocation On-chip memory Tiled matrix multiplication

Using shared memory Matrix multiplication Matrix multiplication uses relatively small amount of arithmetic operations for the amount of memory transfers We need as many operations as possible to hide the latency caused by memory transfers (the GPU tries to schedule the execution units in case of memory latencies but without a lot of operations this is not possible) Out goal is to increase the ratio of arithmetic operations / memory transfers Available solutions Increase parallelism (in this case it is not possible) Decrease the number of memory transfers (in practice this means manually programmed caching) holding as many variables in registers as possible using the shared memory Find another solution 27

Tiled matrix multiplication Tiled matrix technique One input cell is necessary for the calculations of more than one output cell. In the not optimized version of the algorithm, more than one thread will read the same input value from global memory It would be practical to harmonize these thread s work: divide the entire output matrix to small regions (tiles) allocate shared memory for one region in the region, every thread loads the corresponding value from the input matrices to the shared memory every thread calculates one partial result based on the values in the shared memory The size of the shared memory is limited therefore the steps above are usually executable only in more than one steps. We have to divide the input matrix to more than one tiles, and at the and of the kernel executions we have to summarize the values in these tiles The latter case it is necessary to synchronize the threads. Every thread must wait until all of the other threads loads the values from global memory to the shared memory, and after that the threads must wait again until all of them finished calculation before load the next value 28

Optimized matrix multiplication As Bs c B 1. Division to tiles. In this case 3x3 regions, 3x3 threads 2. Every thread copies one value from the global memory to the shared memory 3. Synchronization A C Global memory 29

Optimized matrix multiplication (2) Thread 0,0 As Bs c B 4. Every thread calculated one cell s result in the shared memory 5. Synchronization A C Global memory 30

Optimized matrix multiplication (3) As Bs Thread 0,0 + c B 6. Load next tile 7. Synchronization 8. Threads do the multiplication again. The result added to the already existing partial result 9. Synchronization A C Global memory 31

Optimized matrix multiplication (4) As Bs c B 10. Every thread copies the result to the result matrix C 11. When all of the blocks finished, the C matrix contains the final result A C 32

Optimized matrix multiplication source code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Kernel invocation is the same as the not-optimized version global void MatrixMulGPUTiled(float *deva, float *devb, float *devc) { shared float shr_a[block_size][block_size]; shared float shr_b[block_size][block_size]; } int indx = blockidx.x * BLOCK_SIZE + threadidx.x; int indy = blockidx.y * BLOCK_SIZE + threadidx.y; float c = 0; for (int k = 0; k < N / BLOCK_SIZE; k++) { shr_a[threadidx.y][threadidx.x] = deva[k * BLOCK_SIZE + threadidx.x + indy * N]; shr_b[threadidx.y][threadidx.x] = devb[indx + (k* BLOCK_SIZE + threadidx.y) * N]; syncthreads(); for (int l = 0; l < BLOCK_SIZE; l++) { c += shr_a[threadidx.y][l] * shr_b[l][threadidx.x]; } syncthreads(); } devc[indx + indy * N] = c; 33

Comparing runtime of original and tiled algorithms Runtime of algorithms Horizontal axis: size of matrix (N) Vertical axis: runtime (second) 1 0.9 0.8 0.7 0.6 0.5 0.4 Eredeti Optimalizált 0.3 0.2 0.1 0 40 80 120 160 200 34