From f0779e311840f722c892ae729b6cd3323c5a0940 Mon Sep 17 00:00:00 2001 From: Umesh Seth <umeshseth@login2.crusher.olcf.ornl.gov> Date: Wed, 2 Nov 2022 03:57:58 -0400 Subject: [PATCH 1/9] adds hipInfo code. tested on crusher --- HIP/hipInfo/CMakeLists.txt | 44 ++++++++ HIP/hipInfo/Makefile | 40 +++++++ HIP/hipInfo/README.md | 6 ++ HIP/hipInfo/hipInfo | Bin 0 -> 26552 bytes HIP/hipInfo/hipInfo.cpp | 213 +++++++++++++++++++++++++++++++++++++ 5 files changed, 303 insertions(+) create mode 100644 HIP/hipInfo/CMakeLists.txt create mode 100644 HIP/hipInfo/Makefile create mode 100644 HIP/hipInfo/README.md create mode 100755 HIP/hipInfo/hipInfo create mode 100644 HIP/hipInfo/hipInfo.cpp diff --git a/HIP/hipInfo/CMakeLists.txt b/HIP/hipInfo/CMakeLists.txt new file mode 100644 index 0000000..4314467 --- /dev/null +++ b/HIP/hipInfo/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +project(hipInfo) + +cmake_minimum_required(VERSION 3.10) + +if (NOT DEFINED ROCM_PATH ) + set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) +endif () + +# Search for rocm in common locations +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) + +# Find hip +find_package(hip) + +# Set compiler and linker +set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_BUILD_TYPE Release) + +# Create the excutable +add_executable(hipInfo hipInfo.cpp) + +# Link with HIP +target_link_libraries(hipInfo hip::host) diff --git a/HIP/hipInfo/Makefile b/HIP/hipInfo/Makefile new file mode 100644 index 0000000..ea888ba --- /dev/null +++ b/HIP/hipInfo/Makefile @@ -0,0 +1,40 @@ +# Copyright (c) 2016 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ROCM_PATH?= $(wildcard /opt/rocm/) +HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) +ifeq (,$(HIP_PATH)) + HIP_PATH=../../.. +endif +HIPCC=$(HIP_PATH)/bin/hipcc + +EXE=hipInfo + +#all: install + +$(EXE): hipInfo.cpp + $(HIPCC) hipInfo.cpp -o $@ + +#install: $(EXE) +# cp $(EXE) $(HIP_PATH)/bin + + +clean: + rm -f *.o $(EXE) diff --git a/HIP/hipInfo/README.md b/HIP/hipInfo/README.md new file mode 100644 index 0000000..d52f8d8 --- /dev/null +++ b/HIP/hipInfo/README.md @@ -0,0 +1,6 @@ +# hipInfo + +Simple tool that prints properties for each device (from hipGetDeviceProperties), and compiler info. + Properties includes all of the architectural feature flags for each device. + +Also demonstrates how to use platform-specific compilation path (testing `__HIP_PLATFORM_AMD__` or `__HIP_PLATFORM_NVIDIA__`) diff --git a/HIP/hipInfo/hipInfo b/HIP/hipInfo/hipInfo new file mode 100755 index 0000000000000000000000000000000000000000..82653a090c4f4861b8f7124e3432fdc39e7a9b86 GIT binary patch literal 26552 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 DZ48|` literal 0 HcmV?d00001 diff --git a/HIP/hipInfo/hipInfo.cpp b/HIP/hipInfo/hipInfo.cpp new file mode 100644 index 0000000..28128b6 --- /dev/null +++ b/HIP/hipInfo/hipInfo.cpp @@ -0,0 +1,213 @@ +/* +Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <iostream> +#include <iomanip> +#include "hip/hip_runtime.h" + +#define KNRM "\x1B[0m" +#define KRED "\x1B[31m" +#define KGRN "\x1B[32m" +#define KYEL "\x1B[33m" +#define KBLU "\x1B[34m" +#define KMAG "\x1B[35m" +#define KCYN "\x1B[36m" +#define KWHT "\x1B[37m" + +#define failed(...) \ + printf("%serror: ", KRED); \ + printf(__VA_ARGS__); \ + printf("\n"); \ + printf("error: TEST FAILED\n%s", KNRM); \ + exit(EXIT_FAILURE); + +#define HIPCHECK(error) \ + if (error != hipSuccess) { \ + printf("%serror: '%s'(%d) at %s:%d%s\n", KRED, hipGetErrorString(error), error, __FILE__, \ + __LINE__, KNRM); \ + failed("API returned error code."); \ + } + +void printCompilerInfo() { +#ifdef __NVCC__ + printf("compiler: nvcc\n"); +#endif +} + +double bytesToKB(size_t s) { return (double)s / (1024.0); } +double bytesToGB(size_t s) { return (double)s / (1024.0 * 1024.0 * 1024.0); } + +#define printLimit(w1, limit, units) \ + { \ + size_t val; \ + cudaDeviceGetLimit(&val, limit); \ + std::cout << setw(w1) << #limit ": " << val << " " << units << std::endl; \ + } + + +void printDeviceProp(int deviceId) { + using namespace std; + const int w1 = 34; + + cout << left; + + cout << setw(w1) + << "--------------------------------------------------------------------------------" + << endl; + cout << setw(w1) << "device#" << deviceId << endl; + + hipDeviceProp_t props = {0}; + HIPCHECK(hipGetDeviceProperties(&props, deviceId)); + + cout << setw(w1) << "Name: " << props.name << endl; + cout << setw(w1) << "pciBusID: " << props.pciBusID << endl; + cout << setw(w1) << "pciDeviceID: " << props.pciDeviceID << endl; + cout << setw(w1) << "pciDomainID: " << props.pciDomainID << endl; + cout << setw(w1) << "multiProcessorCount: " << props.multiProcessorCount << endl; + cout << setw(w1) << "maxThreadsPerMultiProcessor: " << props.maxThreadsPerMultiProcessor + << endl; + cout << setw(w1) << "isMultiGpuBoard: " << props.isMultiGpuBoard << endl; + cout << setw(w1) << "clockRate: " << (float)props.clockRate / 1000.0 << " Mhz" << endl; + cout << setw(w1) << "memoryClockRate: " << (float)props.memoryClockRate / 1000.0 << " Mhz" + << endl; + cout << setw(w1) << "memoryBusWidth: " << props.memoryBusWidth << endl; + cout << setw(w1) << "totalGlobalMem: " << fixed << setprecision(2) + << bytesToGB(props.totalGlobalMem) << " GB" << endl; + cout << setw(w1) << "totalConstMem: " << props.totalConstMem << endl; + cout << setw(w1) << "sharedMemPerBlock: " << (float)props.sharedMemPerBlock / 1024.0 << " KB" + << endl; + cout << setw(w1) << "canMapHostMemory: " << props.canMapHostMemory << endl; + cout << setw(w1) << "regsPerBlock: " << props.regsPerBlock << endl; + cout << setw(w1) << "warpSize: " << props.warpSize << endl; + cout << setw(w1) << "l2CacheSize: " << props.l2CacheSize << endl; + cout << setw(w1) << "computeMode: " << props.computeMode << endl; + cout << setw(w1) << "maxThreadsPerBlock: " << props.maxThreadsPerBlock << endl; + cout << setw(w1) << "maxThreadsDim.x: " << props.maxThreadsDim[0] << endl; + cout << setw(w1) << "maxThreadsDim.y: " << props.maxThreadsDim[1] << endl; + cout << setw(w1) << "maxThreadsDim.z: " << props.maxThreadsDim[2] << endl; + cout << setw(w1) << "maxGridSize.x: " << props.maxGridSize[0] << endl; + cout << setw(w1) << "maxGridSize.y: " << props.maxGridSize[1] << endl; + cout << setw(w1) << "maxGridSize.z: " << props.maxGridSize[2] << endl; + cout << setw(w1) << "major: " << props.major << endl; + cout << setw(w1) << "minor: " << props.minor << endl; + cout << setw(w1) << "concurrentKernels: " << props.concurrentKernels << endl; + cout << setw(w1) << "cooperativeLaunch: " << props.cooperativeLaunch << endl; + cout << setw(w1) << "cooperativeMultiDeviceLaunch: " << props.cooperativeMultiDeviceLaunch << endl; + cout << setw(w1) << "isIntegrated: " << props.integrated << endl; + cout << setw(w1) << "maxTexture1D: " << props.maxTexture1D << endl; + cout << setw(w1) << "maxTexture2D.width: " << props.maxTexture2D[0] << endl; + cout << setw(w1) << "maxTexture2D.height: " << props.maxTexture2D[1] << endl; + cout << setw(w1) << "maxTexture3D.width: " << props.maxTexture3D[0] << endl; + cout << setw(w1) << "maxTexture3D.height: " << props.maxTexture3D[1] << endl; + cout << setw(w1) << "maxTexture3D.depth: " << props.maxTexture3D[2] << endl; + +#ifdef __HIP_PLATFORM_AMD__ + cout << setw(w1) << "isLargeBar: " << props.isLargeBar << endl; + cout << setw(w1) << "asicRevision: " << props.asicRevision << endl; + cout << setw(w1) << "maxSharedMemoryPerMultiProcessor: " << fixed << setprecision(2) + << bytesToKB(props.maxSharedMemoryPerMultiProcessor) << " KB" << endl; + cout << setw(w1) << "clockInstructionRate: " << (float)props.clockInstructionRate / 1000.0 + << " Mhz" << endl; + cout << setw(w1) << "arch.hasGlobalInt32Atomics: " << props.arch.hasGlobalInt32Atomics << endl; + cout << setw(w1) << "arch.hasGlobalFloatAtomicExch: " << props.arch.hasGlobalFloatAtomicExch + << endl; + cout << setw(w1) << "arch.hasSharedInt32Atomics: " << props.arch.hasSharedInt32Atomics << endl; + cout << setw(w1) << "arch.hasSharedFloatAtomicExch: " << props.arch.hasSharedFloatAtomicExch + << endl; + cout << setw(w1) << "arch.hasFloatAtomicAdd: " << props.arch.hasFloatAtomicAdd << endl; + cout << setw(w1) << "arch.hasGlobalInt64Atomics: " << props.arch.hasGlobalInt64Atomics << endl; + cout << setw(w1) << "arch.hasSharedInt64Atomics: " << props.arch.hasSharedInt64Atomics << endl; + cout << setw(w1) << "arch.hasDoubles: " << props.arch.hasDoubles << endl; + cout << setw(w1) << "arch.hasWarpVote: " << props.arch.hasWarpVote << endl; + cout << setw(w1) << "arch.hasWarpBallot: " << props.arch.hasWarpBallot << endl; + cout << setw(w1) << "arch.hasWarpShuffle: " << props.arch.hasWarpShuffle << endl; + cout << setw(w1) << "arch.hasFunnelShift: " << props.arch.hasFunnelShift << endl; + cout << setw(w1) << "arch.hasThreadFenceSystem: " << props.arch.hasThreadFenceSystem << endl; + cout << setw(w1) << "arch.hasSyncThreadsExt: " << props.arch.hasSyncThreadsExt << endl; + cout << setw(w1) << "arch.hasSurfaceFuncs: " << props.arch.hasSurfaceFuncs << endl; + cout << setw(w1) << "arch.has3dGrid: " << props.arch.has3dGrid << endl; + cout << setw(w1) << "arch.hasDynamicParallelism: " << props.arch.hasDynamicParallelism << endl; + cout << setw(w1) << "gcnArchName: " << props.gcnArchName << endl; +#endif + int deviceCnt; + hipGetDeviceCount(&deviceCnt); + cout << setw(w1) << "peers: "; + for (int i = 0; i < deviceCnt; i++) { + int isPeer; + hipDeviceCanAccessPeer(&isPeer, i, deviceId); + if (isPeer) { + cout << "device#" << i << " "; + } + } + cout << endl; + cout << setw(w1) << "non-peers: "; + for (int i = 0; i < deviceCnt; i++) { + int isPeer; + hipDeviceCanAccessPeer(&isPeer, i, deviceId); + if (!isPeer) { + cout << "device#" << i << " "; + } + } + cout << endl; + + +#ifdef __HIP_PLATFORM_NVIDIA__ + // Limits: + cout << endl; + printLimit(w1, cudaLimitStackSize, "bytes/thread"); + printLimit(w1, cudaLimitPrintfFifoSize, "bytes/device"); + printLimit(w1, cudaLimitMallocHeapSize, "bytes/device"); + printLimit(w1, cudaLimitDevRuntimeSyncDepth, "grids"); + printLimit(w1, cudaLimitDevRuntimePendingLaunchCount, "launches"); +#endif + + + cout << endl; + + + size_t free, total; + hipMemGetInfo(&free, &total); + + cout << fixed << setprecision(2); + cout << setw(w1) << "memInfo.total: " << bytesToGB(total) << " GB" << endl; + cout << setw(w1) << "memInfo.free: " << bytesToGB(free) << " GB (" << setprecision(0) + << (float)free / total * 100.0 << "%)" << endl; +} + +int main(int argc, char* argv[]) { + using namespace std; + + cout << endl; + + printCompilerInfo(); + + int deviceCnt; + + HIPCHECK(hipGetDeviceCount(&deviceCnt)); + + for (int i = 0; i < deviceCnt; i++) { + hipSetDevice(i); + printDeviceProp(i); + } + + std::cout << std::endl; +} -- GitLab From 8871fec4eea4e6f6b61d874138116fddf8fde70f Mon Sep 17 00:00:00 2001 From: Umesh Seth <umeshseth@login2.crusher.olcf.ornl.gov> Date: Wed, 2 Nov 2022 04:20:13 -0400 Subject: [PATCH 2/9] adds shared memory example --- HIP/shared_memory/CMakeLists.txt | 44 ++++++++++ HIP/shared_memory/Makefile | 57 +++++++++++++ HIP/shared_memory/Readme.md | 42 ++++++++++ HIP/shared_memory/sharedMemory.cpp | 128 +++++++++++++++++++++++++++++ 4 files changed, 271 insertions(+) create mode 100644 HIP/shared_memory/CMakeLists.txt create mode 100644 HIP/shared_memory/Makefile create mode 100644 HIP/shared_memory/Readme.md create mode 100644 HIP/shared_memory/sharedMemory.cpp diff --git a/HIP/shared_memory/CMakeLists.txt b/HIP/shared_memory/CMakeLists.txt new file mode 100644 index 0000000..f2f5196 --- /dev/null +++ b/HIP/shared_memory/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +project(sharedMemory) + +cmake_minimum_required(VERSION 3.10) + +if (NOT DEFINED ROCM_PATH ) + set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) +endif () + +# Search for rocm in common locations +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) + +# Find hip +find_package(hip) + +# Set compiler and linker +set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_BUILD_TYPE Release) + +# Create the excutable +add_executable(sharedMemory sharedMemory.cpp) + +# Link with HIP +target_link_libraries(sharedMemory hip::host) diff --git a/HIP/shared_memory/Makefile b/HIP/shared_memory/Makefile new file mode 100644 index 0000000..ef8727c --- /dev/null +++ b/HIP/shared_memory/Makefile @@ -0,0 +1,57 @@ +# Copyright (c) 2016 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ROCM_PATH?= $(wildcard /opt/rocm/) +HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) +ifeq (,$(HIP_PATH)) + HIP_PATH=../../.. +endif + +HIPCC=$(HIP_PATH)/bin/hipcc + +TARGET=hcc + +SOURCES = sharedMemory.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +EXECUTABLE=./sharedMemory + +.PHONY: test + + +all: $(EXECUTABLE) test + +CXXFLAGS =-g +CXX=$(HIPCC) + + +$(EXECUTABLE): $(OBJECTS) + $(HIPCC) $(OBJECTS) -o $@ + + +test: $(EXECUTABLE) + $(EXECUTABLE) + + +clean: + rm -f $(EXECUTABLE) + rm -f $(OBJECTS) + rm -f $(HIP_PATH)/src/*.o + diff --git a/HIP/shared_memory/Readme.md b/HIP/shared_memory/Readme.md new file mode 100644 index 0000000..756cb6e --- /dev/null +++ b/HIP/shared_memory/Readme.md @@ -0,0 +1,42 @@ +## Using shared memory ### + +Earlier we learned how to write our first hip program, in which we compute Matrix Transpose. In this tutorial, we'll explain how to use the shared memory to improve the performance. + +## Introduction: + +As we mentioned earlier that Memory bottlenecks is the main problem why we are not able to get the highest performance, therefore minimizing the latency for memory access plays prominent role in application optimization. In this tutorial, we'll learn how to use static shared memory and will explain the dynamic one latter. + +## Requirement: +For hardware requirement and software installation [Installation](https://github.com/ROCm-Developer-Tools/HIP/blob/master/INSTALL.md) + +## prerequiste knowledge: + +Programmers familiar with CUDA, OpenCL will be able to quickly learn and start coding with the HIP API. In case you are not, don't worry. You choose to start with the best one. We'll be explaining everything assuming you are completely new to gpgpu programming. + +## Simple Matrix Transpose + +We will be using the Simple Matrix Transpose application from the previous tutorial and modify it to learn how to use shared memory. + +## Shared Memory + +Shared memory is way more faster than that of global and constant memory and accessible to all the threads in the block. If the size of shared memory is known at compile time, we can specify the size and will use the static shared memory. In the same sourcecode, we will use the `__shared__` variable type qualifier as follows: + +` __shared__ float sharedMem[1024*1024];` + +Be careful while using shared memory, since all threads within the block can access the shared memory, we need to sync the operation of individual threads by using: + +` __syncthreads();` + +## How to build and run: +Use the make command and execute it using ./exe +Use hipcc to build the application, which is using hcc on AMD and nvcc on nvidia. + +## More Info: +- [HIP FAQ](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_faq.md) +- [HIP Kernel Language](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_kernel_language.md) +- [HIP Runtime API (Doxygen)](http://rocm-developer-tools.github.io/HIP) +- [HIP Porting Guide](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_porting_guide.md) +- [HIP Terminology](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_terms.md) (including Rosetta Stone of GPU computing terms across CUDA/HIP/HC/AMP/OpenL) +- [HIPIFY](https://github.com/ROCm-Developer-Tools/HIPIFY/blob/master/README.md) +- [Developer/CONTRIBUTING Info](https://github.com/ROCm-Developer-Tools/HIP/blob/master/CONTRIBUTING.md) +- [Release Notes](https://github.com/ROCm-Developer-Tools/HIP/blob/master/RELEASE.md) diff --git a/HIP/shared_memory/sharedMemory.cpp b/HIP/shared_memory/sharedMemory.cpp new file mode 100644 index 0000000..cff03f0 --- /dev/null +++ b/HIP/shared_memory/sharedMemory.cpp @@ -0,0 +1,128 @@ +/* +Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <iostream> + +// hip header file +#include "hip/hip_runtime.h" + + +#define WIDTH 64 + +#define NUM (WIDTH * WIDTH) + +#define THREADS_PER_BLOCK_X 4 +#define THREADS_PER_BLOCK_Y 4 +#define THREADS_PER_BLOCK_Z 1 + +// Device (Kernel) function, it must be void +__global__ void matrixTranspose(float* out, float* in, const int width) { + __shared__ float sharedMem[WIDTH * WIDTH]; + + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + + sharedMem[y * width + x] = in[x * width + y]; + + __syncthreads(); + + out[y * width + x] = sharedMem[y * width + x]; +} + +// CPU implementation of matrix transpose +void matrixTransposeCPUReference(float* output, float* input, const unsigned int width) { + for (unsigned int j = 0; j < width; j++) { + for (unsigned int i = 0; i < width; i++) { + output[i * width + j] = input[j * width + i]; + } + } +} + +int main() { + float* Matrix; + float* TransposeMatrix; + float* cpuTransposeMatrix; + + float* gpuMatrix; + float* gpuTransposeMatrix; + + hipDeviceProp_t devProp; + hipGetDeviceProperties(&devProp, 0); + + std::cout << "Device name " << devProp.name << std::endl; + + int i; + int errors; + + Matrix = (float*)malloc(NUM * sizeof(float)); + TransposeMatrix = (float*)malloc(NUM * sizeof(float)); + cpuTransposeMatrix = (float*)malloc(NUM * sizeof(float)); + + // initialize the input data + for (i = 0; i < NUM; i++) { + Matrix[i] = (float)i * 10.0f; + } + + // allocate the memory on the device side + hipMalloc((void**)&gpuMatrix, NUM * sizeof(float)); + hipMalloc((void**)&gpuTransposeMatrix, NUM * sizeof(float)); + + // Memory transfer from host to device + hipMemcpy(gpuMatrix, Matrix, NUM * sizeof(float), hipMemcpyHostToDevice); + + // Lauching kernel from host + hipLaunchKernelGGL(matrixTranspose, dim3(WIDTH / THREADS_PER_BLOCK_X, WIDTH / THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), 0, 0, gpuTransposeMatrix, + gpuMatrix, WIDTH); + + // Memory transfer from device to host + hipMemcpy(TransposeMatrix, gpuTransposeMatrix, NUM * sizeof(float), hipMemcpyDeviceToHost); + + // CPU MatrixTranspose computation + matrixTransposeCPUReference(cpuTransposeMatrix, Matrix, WIDTH); + + // verify the results + errors = 0; + double eps = 1.0E-6; + for (i = 0; i < NUM; i++) { + if (std::abs(TransposeMatrix[i] - cpuTransposeMatrix[i]) > eps) { + printf("%d cpu: %f gpu %f\n", i, cpuTransposeMatrix[i], TransposeMatrix[i]); + errors++; + } + } + if (errors != 0) { + printf("FAILED: %d errors\n", errors); + } else { + printf("PASSED!\n"); + } + + // free the resources on device side + hipFree(gpuMatrix); + hipFree(gpuTransposeMatrix); + + // free the resources on host side + free(Matrix); + free(TransposeMatrix); + free(cpuTransposeMatrix); + + return errors; +} -- GitLab From 091a39798359d71cb750c80d1dbafee0a757e3cd Mon Sep 17 00:00:00 2001 From: Umesh Seth <umeshseth@login2.crusher.olcf.ornl.gov> Date: Wed, 2 Nov 2022 04:20:57 -0400 Subject: [PATCH 3/9] adds MatrixTranspose example --- HIP/MatrixTranspose/CMakeLists.txt | 44 +++++++++ HIP/MatrixTranspose/Makefile | 57 +++++++++++ HIP/MatrixTranspose/MatrixTranspose.cpp | 122 ++++++++++++++++++++++++ HIP/MatrixTranspose/Readme.md | 101 ++++++++++++++++++++ 4 files changed, 324 insertions(+) create mode 100644 HIP/MatrixTranspose/CMakeLists.txt create mode 100644 HIP/MatrixTranspose/Makefile create mode 100644 HIP/MatrixTranspose/MatrixTranspose.cpp create mode 100644 HIP/MatrixTranspose/Readme.md diff --git a/HIP/MatrixTranspose/CMakeLists.txt b/HIP/MatrixTranspose/CMakeLists.txt new file mode 100644 index 0000000..ae4735c --- /dev/null +++ b/HIP/MatrixTranspose/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +project(MatrixTranspose) + +cmake_minimum_required(VERSION 3.10) + +if (NOT DEFINED ROCM_PATH ) + set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) +endif () + +# Search for rocm in common locations +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) + +# Find hip +find_package(hip) + +# Set compiler and linker +set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_BUILD_TYPE Release) + +# Create the excutable +add_executable(MatrixTranspose MatrixTranspose.cpp) + +# Link with HIP +target_link_libraries(MatrixTranspose hip::host) diff --git a/HIP/MatrixTranspose/Makefile b/HIP/MatrixTranspose/Makefile new file mode 100644 index 0000000..4e829bd --- /dev/null +++ b/HIP/MatrixTranspose/Makefile @@ -0,0 +1,57 @@ +# Copyright (c) 2016 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ROCM_PATH?= $(wildcard /opt/rocm/) +HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) +ifeq (,$(HIP_PATH)) + HIP_PATH=../../.. +endif + +HIPCC=$(HIP_PATH)/bin/hipcc + +TARGET=hcc + +SOURCES = MatrixTranspose.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +EXECUTABLE=./MatrixTranspose + +.PHONY: test + + +all: $(EXECUTABLE) test + +CXXFLAGS =-g +CXX=$(HIPCC) + + +$(EXECUTABLE): $(OBJECTS) + $(HIPCC) $(OBJECTS) -o $@ + + +test: $(EXECUTABLE) + $(EXECUTABLE) + + +clean: + rm -f $(EXECUTABLE) + rm -f $(OBJECTS) + rm -f $(HIP_PATH)/src/*.o + diff --git a/HIP/MatrixTranspose/MatrixTranspose.cpp b/HIP/MatrixTranspose/MatrixTranspose.cpp new file mode 100644 index 0000000..2457505 --- /dev/null +++ b/HIP/MatrixTranspose/MatrixTranspose.cpp @@ -0,0 +1,122 @@ +/* +Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <iostream> + +// hip header file +#include "hip/hip_runtime.h" + + +#define WIDTH 1024 + + +#define NUM (WIDTH * WIDTH) + +#define THREADS_PER_BLOCK_X 4 +#define THREADS_PER_BLOCK_Y 4 +#define THREADS_PER_BLOCK_Z 1 + +// Device (Kernel) function, it must be void +__global__ void matrixTranspose(float* out, float* in, const int width) { + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + + out[y * width + x] = in[x * width + y]; +} + +// CPU implementation of matrix transpose +void matrixTransposeCPUReference(float* output, float* input, const unsigned int width) { + for (unsigned int j = 0; j < width; j++) { + for (unsigned int i = 0; i < width; i++) { + output[i * width + j] = input[j * width + i]; + } + } +} + +int main() { + float* Matrix; + float* TransposeMatrix; + float* cpuTransposeMatrix; + + float* gpuMatrix; + float* gpuTransposeMatrix; + + hipDeviceProp_t devProp; + hipGetDeviceProperties(&devProp, 0); + + std::cout << "Device name " << devProp.name << std::endl; + + int i; + int errors; + + Matrix = (float*)malloc(NUM * sizeof(float)); + TransposeMatrix = (float*)malloc(NUM * sizeof(float)); + cpuTransposeMatrix = (float*)malloc(NUM * sizeof(float)); + + // initialize the input data + for (i = 0; i < NUM; i++) { + Matrix[i] = (float)i * 10.0f; + } + + // allocate the memory on the device side + hipMalloc((void**)&gpuMatrix, NUM * sizeof(float)); + hipMalloc((void**)&gpuTransposeMatrix, NUM * sizeof(float)); + + // Memory transfer from host to device + hipMemcpy(gpuMatrix, Matrix, NUM * sizeof(float), hipMemcpyHostToDevice); + + // Lauching kernel from host + hipLaunchKernelGGL(matrixTranspose, dim3(WIDTH / THREADS_PER_BLOCK_X, WIDTH / THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), 0, 0, gpuTransposeMatrix, + gpuMatrix, WIDTH); + + // Memory transfer from device to host + hipMemcpy(TransposeMatrix, gpuTransposeMatrix, NUM * sizeof(float), hipMemcpyDeviceToHost); + + // CPU MatrixTranspose computation + matrixTransposeCPUReference(cpuTransposeMatrix, Matrix, WIDTH); + + // verify the results + errors = 0; + double eps = 1.0E-6; + for (i = 0; i < NUM; i++) { + if (std::abs(TransposeMatrix[i] - cpuTransposeMatrix[i]) > eps) { + errors++; + } + } + if (errors != 0) { + printf("FAILED: %d errors\n", errors); + } else { + printf("PASSED!\n"); + } + + // free the resources on device side + hipFree(gpuMatrix); + hipFree(gpuTransposeMatrix); + + // free the resources on host side + free(Matrix); + free(TransposeMatrix); + free(cpuTransposeMatrix); + + return errors; +} diff --git a/HIP/MatrixTranspose/Readme.md b/HIP/MatrixTranspose/Readme.md new file mode 100644 index 0000000..432f918 --- /dev/null +++ b/HIP/MatrixTranspose/Readme.md @@ -0,0 +1,101 @@ +## Writing first HIP program ### + +This tutorial shows how to get write simple HIP application. We will write the simplest Matrix Transpose program. + +## HIP Introduction: + +HIP is a C++ runtime API and kernel language that allows developers to create portable applications that can run on AMD and other GPU’s. Our goal was to rise above the lowest-common-denominator paths and deliver a solution that allows you, the developer, to use essential hardware features and maximize your application’s performance on GPU hardware. + +## Requirement: +For hardware requirement and software installation [Installation](https://github.com/ROCm-Developer-Tools/HIP/blob/master/INSTALL.md) + +## prerequiste knowledge: + +Programmers familiar with CUDA, OpenCL will be able to quickly learn and start coding with the HIP API. In case you are not, don't worry. You choose to start with the best one. We'll be explaining everything assuming you are completely new to gpgpu programming. + +## Simple Matrix Transpose + +Here is simple example showing how to write your first program in HIP. +In order to use the HIP framework, we need to add the "hip_runtime.h" header file. SInce its c++ api you can add any header file you have been using earlier while writing your c/c++ program. For gpgpu programming, we have host(microprocessor) and the device(gpu). + +## Device-side code +We will work on device side code first, Here is simple example showing a snippet of HIP device side code: + +``` +__global__ void matrixTranspose(float *out, + float *in, + const int width, + const int height) +{ + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + + out[y * width + x] = in[x * height + y]; +} +``` + +`__global__` keyword is the Function-Type Qualifiers, it is used with functions that are executed on device and are called/launched from the hosts. +other function-type qualifiers are: +`__device__` functions are Executed on the device and Called from the device only +`__host__` functions are Executed on the host and Called from the host + +`__host__` can combine with `__device__`, in which case the function compiles for both the host and device. These functions cannot use the HIP grid coordinate functions (for example, "hipThreadIdx_x", will talk about it latter). A possible workaround is to pass the necessary coordinate info as an argument to the function. +`__host__` cannot combine with `__global__`. + +`__global__` functions are often referred to as *kernels*, and calling one is termed *launching the kernel*. + +Next keyword is `void`. HIP `__global__` functions must have a `void` return type. Global functions require the caller to specify an "execution configuration" that includes the grid and block dimensions. The execution configuration can also include other information for the launch, such as the amount of additional shared memory to allocate and the stream where the kernel should execute. + +The kernel function begins with +` int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x;` +` int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y;` +here the keyword hipBlockIdx_x, hipBlockIdx_y and hipBlockIdx_z(not used here) are the built-in functions to identify the threads in a block. The keyword hipBlockDim_x, hipBlockDim_y and hipBlockDim_z(not used here) are to identify the dimensions of the block. + +We are familiar with rest of the code on device-side. + +## Host-side code + +Now, we'll see how to call the kernel from the host. Inside the main() function, we first defined the pointers(for both, the host-side as well as device). The declaration of device pointer is similar to that of the host. Next, we have `hipDeviceProp_t`, it is the pre-defined struct for hip device properties. This is followed by `hipGetDeviceProperties(&devProp, 0)` It is used to extract the device information. The first parameter is the struct, second parameter is the device number to get properties for. Next line print the name of the device. + +We allocated memory to the Matrix on host side by using malloc and initiallized it. While in order to allocate memory on device side we will be using `hipMalloc`, it's quiet similar to that of malloc instruction. After this, we will copy the data to the allocated memory on device-side using `hipMemcpy`. +` hipMemcpy(gpuMatrix, Matrix, NUM*sizeof(float), hipMemcpyHostToDevice);` +here the first parameter is the destination pointer, second is the source pointer, third is the size of memory copy and the last specify the direction on memory copy(which is in this case froom host to device). While in order to transfer memory from device to host, use `hipMemcpyDeviceToHost` and for device to device memory copy use `hipMemcpyDeviceToDevice`. + +Now, we'll see how to launch the kernel. +``` + hipLaunchKernelGGL(matrixTranspose, + dim3(WIDTH/THREADS_PER_BLOCK_X, HEIGHT/THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), + 0, 0, + gpuTransposeMatrix , gpuMatrix, WIDTH ,HEIGHT); +``` + +HIP introduces a standard C++ calling convention to pass the execution configuration to the kernel (this convention replaces the `Cuda <<< >>>` syntax). In HIP, +- Kernels launch with the `"hipLaunchKernelGGL"` function +- The first five parameters to hipLaunchKernelGGL are the following: + - **symbol kernelName**: the name of the kernel to launch. To support template kernels which contains "," use the HIP_KERNEL_NAME macro. In current application it's "matrixTranspose". + - **dim3 gridDim**: 3D-grid dimensions specifying the number of blocks to launch. In MatrixTranspose sample, it's "dim3(WIDTH/THREADS_PER_BLOCK_X, HEIGHT/THREADS_PER_BLOCK_Y)". + - **dim3 blockDim**: 3D-block dimensions specifying the number of threads in each block.In MatrixTranspose sample, it's "dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y)". + - **size_t dynamicShared**: amount of additional shared memory to allocate when launching the kernel. In MatrixTranspose sample, it's '0'. + - **hipStream_t**: stream where the kernel should execute. A value of 0 corresponds to the NULL stream.In MatrixTranspose sample, it's '0'. +- Kernel arguments follow these first five parameters. Here, these are "gpuTransposeMatrix , gpuMatrix, WIDTH ,HEIGHT". + +Next, we'll copy the computed values/data back to the device using the `hipMemcpy`. Here the last parameter will be `hipMemcpyDeviceToHost` + +After, copying the data from device to memory, we will verify it with the one we computed with the cpu reference funtion. + +Finally, we will free the memory allocated earlier by using free() for host while for devices we will use `hipFree`. + +## How to build and run: +Use the make command and execute it using ./exe +Use hipcc to build the application, which is using hcc on AMD and nvcc on nvidia. + +## More Info: +- [HIP FAQ](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_faq.md) +- [HIP Kernel Language](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_kernel_language.md) +- [HIP Runtime API (Doxygen)](http://rocm-developer-tools.github.io/HIP) +- [HIP Porting Guide](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_porting_guide.md) +- [HIP Terminology](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_terms.md) (including Rosetta Stone of GPU computing terms across CUDA/HIP/HC/AMP/OpenL) +- [HIPIFY](https://github.com/ROCm-Developer-Tools/HIPIFY/blob/master/README.md) +- [Developer/CONTRIBUTING Info](https://github.com/ROCm-Developer-Tools/HIP/blob/master/CONTRIBUTING.md) +- [Release Notes](https://github.com/ROCm-Developer-Tools/HIP/blob/master/RELEASE.md) -- GitLab From f44bcc679bd9a4eca887f16d6b2d16b5bf1992b9 Mon Sep 17 00:00:00 2001 From: Umesh Seth <umeshseth@login2.crusher.olcf.ornl.gov> Date: Wed, 2 Nov 2022 04:21:16 -0400 Subject: [PATCH 4/9] adds hipEvent example --- HIP/hipEvent/CMakeLists.txt | 44 ++++++++++ HIP/hipEvent/Makefile | 57 +++++++++++++ HIP/hipEvent/Readme.md | 80 ++++++++++++++++++ HIP/hipEvent/hipEvent.cpp | 158 ++++++++++++++++++++++++++++++++++++ 4 files changed, 339 insertions(+) create mode 100644 HIP/hipEvent/CMakeLists.txt create mode 100644 HIP/hipEvent/Makefile create mode 100644 HIP/hipEvent/Readme.md create mode 100644 HIP/hipEvent/hipEvent.cpp diff --git a/HIP/hipEvent/CMakeLists.txt b/HIP/hipEvent/CMakeLists.txt new file mode 100644 index 0000000..9ac1aba --- /dev/null +++ b/HIP/hipEvent/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +project(hipEvent) + +cmake_minimum_required(VERSION 3.10) + +if (NOT DEFINED ROCM_PATH ) + set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) +endif () + +# Search for rocm in common locations +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) + +# Find hip +find_package(hip) + +# Set compiler and linker +set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_BUILD_TYPE Release) + +# Create the excutable +add_executable(hipEvent hipEvent.cpp) + +# Link with HIP +target_link_libraries(hipEvent hip::host) diff --git a/HIP/hipEvent/Makefile b/HIP/hipEvent/Makefile new file mode 100644 index 0000000..01655bd --- /dev/null +++ b/HIP/hipEvent/Makefile @@ -0,0 +1,57 @@ +# Copyright (c) 2016 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ROCM_PATH?= $(wildcard /opt/rocm/) +HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) +ifeq (,$(HIP_PATH)) + HIP_PATH=../../.. +endif + +HIPCC=$(HIP_PATH)/bin/hipcc + +TARGET=hcc + +SOURCES = hipEvent.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +EXECUTABLE=./hipEvent + +.PHONY: test + + +all: $(EXECUTABLE) test + +CXXFLAGS =-g +CXX=$(HIPCC) + + +$(EXECUTABLE): $(OBJECTS) + $(HIPCC) $(OBJECTS) -o $@ + + +test: $(EXECUTABLE) + $(EXECUTABLE) + + +clean: + rm -f $(EXECUTABLE) + rm -f $(OBJECTS) + rm -f $(HIP_PATH)/src/*.o + diff --git a/HIP/hipEvent/Readme.md b/HIP/hipEvent/Readme.md new file mode 100644 index 0000000..2bd389e --- /dev/null +++ b/HIP/hipEvent/Readme.md @@ -0,0 +1,80 @@ +## Using hipEvents to measure performance ### + +This tutorial is follow-up of the previous one where we learn how to write our first hip program, in which we compute Matrix Transpose. In this tutorial, we'll explain how to use the hipEvent to get the performance score for memory transfer and kernel execution time. + +## Introduction: + +Memory transfer and kernel execution are the most important parameter in parallel computing (specially HPC and machine learning). Memory bottlenecks is the main problem why we are not able to get the highest performance, therefore obtaining the memory transfer timing and kernel execution timing plays key role in application optimization. + +## Requirement: +For hardware requirement and software installation [Installation](https://github.com/ROCm-Developer-Tools/HIP/blob/master/INSTALL.md) + +## prerequiste knowledge: + +Programmers familiar with CUDA, OpenCL will be able to quickly learn and start coding with the HIP API. In case you are not, don't worry. You choose to start with the best one. We'll be explaining everything assuming you are completely new to gpgpu programming. + +## Simple Matrix Transpose + +We will be using the Simple Matrix Transpose application from the previous tutorial and modify it to learn how to get the performance score for memory transfer and kernel execution time. + +## hipEvent_t + +We'll learn how to use the event management functionality of HIP runtime api. In the same sourcecode, we used for MatrixTranspose we will declare the following events as follows: + +``` + hipEvent_t start, stop; +``` + +We'll create the event with the help of following code: + +``` + hipEventCreate(&start); + hipEventCreate(&stop); +``` + +We'll use the "eventMs" variable to store the time taken value: +` float eventMs = 1.0f;` + +## Time taken measurement by using hipEvents: + +We'll start the timer by calling: +` hipEventRecord(start, NULL);` +in this, the first parameter is the hipEvent_t, will will mark the start of the time from which the measurement has to be performed, while the second parameter has to be of the type hipStream_t. In current situation, we have passed NULL (the default stream). We will learn about the `hipStream_t` in more detail latter. + +Now, we'll have the operation for which we need to compute the time taken. For the case of memory transfer, we'll place the `hipMemcpy`: +` hipMemcpy(gpuMatrix, Matrix, NUM*sizeof(float), hipMemcpyHostToDevice);` + +and for kernel execution time we'll use `hipKernelLaunch`: +``` +hipLaunchKernelGGL(matrixTranspose, + dim3(WIDTH/THREADS_PER_BLOCK_X, HEIGHT/THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), + 0, 0, + gpuTransposeMatrix , gpuMatrix, WIDTH ,HEIGHT); +``` + +Now to mark the end of the eventRecord, we will again use the hipEventRecord by passing the stop event: +` hipEventRecord(stop, NULL);` + +Will synchronize the event with the help of: +` hipEventSynchronize(stop);` + +In order to calculate the time taken by measuring the difference of occurance marked by the start and stop event, we'll use: +` hipEventElapsedTime(&eventMs, start, stop);` +Here the first parameter will store the time taken value, second parameter is the starting marker for the event while the third one is marking the end. + +We can print the value of time take comfortably since eventMs is float variable. + +## How to build and run: +Use the make command and execute it using ./exe +Use hipcc to build the application, which is using hcc on AMD and nvcc on nvidia. + +## More Info: +- [HIP FAQ](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_faq.md) +- [HIP Kernel Language](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_kernel_language.md) +- [HIP Runtime API (Doxygen)](http://rocm-developer-tools.github.io/HIP) +- [HIP Porting Guide](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_porting_guide.md) +- [HIP Terminology](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_terms.md) (including Rosetta Stone of GPU computing terms across CUDA/HIP/HC/AMP/OpenL) +- [HIPIFY](https://github.com/ROCm-Developer-Tools/HIPIFY/blob/master/README.md) +- [Developer/CONTRIBUTING Info](https://github.com/ROCm-Developer-Tools/HIP/blob/master/CONTRIBUTING.md) +- [Release Notes](https://github.com/ROCm-Developer-Tools/HIP/blob/master/RELEASE.md) diff --git a/HIP/hipEvent/hipEvent.cpp b/HIP/hipEvent/hipEvent.cpp new file mode 100644 index 0000000..a83b99b --- /dev/null +++ b/HIP/hipEvent/hipEvent.cpp @@ -0,0 +1,158 @@ +/* +Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <iostream> + +// hip header file +#include "hip/hip_runtime.h" + +#define WIDTH 1024 + +#define NUM (WIDTH * WIDTH) + +#define THREADS_PER_BLOCK_X 4 +#define THREADS_PER_BLOCK_Y 4 +#define THREADS_PER_BLOCK_Z 1 + +// Device (Kernel) function, it must be void +__global__ void matrixTranspose(float* out, float* in, const int width) { + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + + out[y * width + x] = in[x * width + y]; +} + +// CPU implementation of matrix transpose +void matrixTransposeCPUReference(float* output, float* input, const unsigned int width) { + for (unsigned int j = 0; j < width; j++) { + for (unsigned int i = 0; i < width; i++) { + output[i * width + j] = input[j * width + i]; + } + } +} + +int main() { + float* Matrix; + float* TransposeMatrix; + float* cpuTransposeMatrix; + + float* gpuMatrix; + float* gpuTransposeMatrix; + + hipDeviceProp_t devProp; + hipGetDeviceProperties(&devProp, 0); + + std::cout << "Device name " << devProp.name << std::endl; + + hipEvent_t start, stop; + hipEventCreate(&start); + hipEventCreate(&stop); + float eventMs = 1.0f; + + int i; + int errors; + + Matrix = (float*)malloc(NUM * sizeof(float)); + TransposeMatrix = (float*)malloc(NUM * sizeof(float)); + cpuTransposeMatrix = (float*)malloc(NUM * sizeof(float)); + + // initialize the input data + for (i = 0; i < NUM; i++) { + Matrix[i] = (float)i * 10.0f; + } + + // allocate the memory on the device side + hipMalloc((void**)&gpuMatrix, NUM * sizeof(float)); + hipMalloc((void**)&gpuTransposeMatrix, NUM * sizeof(float)); + + // Record the start event + hipEventRecord(start, NULL); + + // Memory transfer from host to device + hipMemcpy(gpuMatrix, Matrix, NUM * sizeof(float), hipMemcpyHostToDevice); + + // Record the stop event + hipEventRecord(stop, NULL); + hipEventSynchronize(stop); + + hipEventElapsedTime(&eventMs, start, stop); + + printf("hipMemcpyHostToDevice time taken = %6.3fms\n", eventMs); + + // Record the start event + hipEventRecord(start, NULL); + + // Lauching kernel from host + hipLaunchKernelGGL(matrixTranspose, dim3(WIDTH / THREADS_PER_BLOCK_X, WIDTH / THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), 0, 0, gpuTransposeMatrix, + gpuMatrix, WIDTH); + + // Record the stop event + hipEventRecord(stop, NULL); + hipEventSynchronize(stop); + + hipEventElapsedTime(&eventMs, start, stop); + + printf("kernel Execution time = %6.3fms\n", eventMs); + + // Record the start event + hipEventRecord(start, NULL); + + // Memory transfer from device to host + hipMemcpy(TransposeMatrix, gpuTransposeMatrix, NUM * sizeof(float), hipMemcpyDeviceToHost); + + // Record the stop event + hipEventRecord(stop, NULL); + hipEventSynchronize(stop); + + hipEventElapsedTime(&eventMs, start, stop); + + printf("hipMemcpyDeviceToHost time taken = %6.3fms\n", eventMs); + + // CPU MatrixTranspose computation + matrixTransposeCPUReference(cpuTransposeMatrix, Matrix, WIDTH); + + // verify the results + errors = 0; + double eps = 1.0E-6; + for (i = 0; i < NUM; i++) { + if (std::abs(TransposeMatrix[i] - cpuTransposeMatrix[i]) > eps) { + errors++; + } + } + if (errors != 0) { + printf("FAILED: %d errors\n", errors); + } else { + printf("PASSED!\n"); + } + + // free the resources on device side + hipFree(gpuMatrix); + hipFree(gpuTransposeMatrix); + + // free the resources on host side + free(Matrix); + free(TransposeMatrix); + free(cpuTransposeMatrix); + + return errors; +} -- GitLab From 315b50c582c931bc73effc3b34cae262c527c165 Mon Sep 17 00:00:00 2001 From: Umesh Seth <umeshseth@login2.crusher.olcf.ornl.gov> Date: Wed, 2 Nov 2022 04:27:15 -0400 Subject: [PATCH 5/9] add hipStreams example --- HIP/hipStreams/CMakeLists.txt | 43 +++++++++++ HIP/hipStreams/Makefile | 57 ++++++++++++++ HIP/hipStreams/Readme.md | 63 ++++++++++++++++ HIP/hipStreams/stream.cpp | 138 ++++++++++++++++++++++++++++++++++ 4 files changed, 301 insertions(+) create mode 100644 HIP/hipStreams/CMakeLists.txt create mode 100644 HIP/hipStreams/Makefile create mode 100644 HIP/hipStreams/Readme.md create mode 100644 HIP/hipStreams/stream.cpp diff --git a/HIP/hipStreams/CMakeLists.txt b/HIP/hipStreams/CMakeLists.txt new file mode 100644 index 0000000..2d95541 --- /dev/null +++ b/HIP/hipStreams/CMakeLists.txt @@ -0,0 +1,43 @@ +# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +project(stream) + +cmake_minimum_required(VERSION 3.10) + +if (NOT DEFINED ROCM_PATH ) + set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) +endif () + +# Search for rocm in common locations +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) + +# Find hip +find_package(hip) + +# Set compiler and linker +set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) + +# Create the excutable +add_executable(stream stream.cpp) + +# Link with HIP +target_link_libraries(stream hip::host) diff --git a/HIP/hipStreams/Makefile b/HIP/hipStreams/Makefile new file mode 100644 index 0000000..814341b --- /dev/null +++ b/HIP/hipStreams/Makefile @@ -0,0 +1,57 @@ +# Copyright (c) 2016 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ROCM_PATH?= $(wildcard /opt/rocm/) +HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) +ifeq (,$(HIP_PATH)) + HIP_PATH=../../.. +endif + +HIPCC=$(HIP_PATH)/bin/hipcc + +TARGET=hcc + +SOURCES = stream.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +EXECUTABLE=./stream + +.PHONY: test + + +all: $(EXECUTABLE) test + +CXXFLAGS =-g +CXX=$(HIPCC) + + +$(EXECUTABLE): $(OBJECTS) + $(HIPCC) $(OBJECTS) -o $@ + + +test: $(EXECUTABLE) + $(EXECUTABLE) + + +clean: + rm -f $(EXECUTABLE) + rm -f $(OBJECTS) + rm -f $(HIP_PATH)/src/*.o + diff --git a/HIP/hipStreams/Readme.md b/HIP/hipStreams/Readme.md new file mode 100644 index 0000000..14b6a97 --- /dev/null +++ b/HIP/hipStreams/Readme.md @@ -0,0 +1,63 @@ +## Streams ### + +In all Earlier tutorial we used single stream, In this tutorial, we'll explain how to launch multiple streams. + +## Introduction: + +The various instances of kernel to be executed on device in exact launch order defined by Host are called streams. We can launch multiple streams on a single device. We will learn how to learn two streams which can we scaled with ease. + +## Requirement: +For hardware requirement and software installation [Installation](https://github.com/ROCm-Developer-Tools/HIP/blob/master/INSTALL.md) + +## prerequiste knowledge: + +Programmers familiar with CUDA, OpenCL will be able to quickly learn and start coding with the HIP API. In case you are not, don't worry. You choose to start with the best one. We'll be explaining everything assuming you are completely new to gpgpu programming. + +## Simple Matrix Transpose + +We will be using the Simple Matrix Transpose application from the previous tutorial and modify it to learn how to launch multiple streams. + +## Streams + +In this tutorial, we'll use both instances of shared memory (i.e., static and dynamic) as different streams. We declare stream as follows: +` hipStream_t streams[num_streams]; ` + +and create stream using `hipStreamCreate` as follows: +``` +for(int i=0;i<num_streams;i++) + hipStreamCreate(&streams[i]); +``` + +and while kernel launch, we make the following changes in 5th parameter to hipLaunchKernelGGL(having 0 as the default stream value): + +``` + hipLaunchKernelGGL(matrixTranspose_static_shared, + dim3(WIDTH/THREADS_PER_BLOCK_X, WIDTH/THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), + 0, streams[0], + gpuTransposeMatrix[0], data[0], width); +``` + +``` + hipLaunchKernelGGL(matrixTranspose_dynamic_shared, + dim3(WIDTH/THREADS_PER_BLOCK_X, WIDTH/THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), + sizeof(float)*WIDTH*WIDTH, streams[1], + gpuTransposeMatrix[1], data[1], width); +``` + +here we replaced 4th parameter with amount of additional shared memory to allocate when launching the kernel. + +## How to build and run: +Use the make command and execute it using ./exe +Use hipcc to build the application, which is using hcc on AMD and nvcc on nvidia. + +## More Info: +- [HIP FAQ](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_faq.md) +- [HIP Kernel Language](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_kernel_language.md) +- [HIP Runtime API (Doxygen)](http://rocm-developer-tools.github.io/HIP) +- [HIP Porting Guide](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_porting_guide.md) +- [HIP Terminology](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_terms.md) (including Rosetta Stone of GPU computing terms across CUDA/HIP/HC/AMP/OpenL) +- [HIPIFY](https://github.com/ROCm-Developer-Tools/HIPIFY/blob/master/README.md) +- [Developer/CONTRIBUTING Info](https://github.com/ROCm-Developer-Tools/HIP/blob/master/CONTRIBUTING.md) +- [Release Notes](https://github.com/ROCm-Developer-Tools/HIP/blob/master/RELEASE.md) diff --git a/HIP/hipStreams/stream.cpp b/HIP/hipStreams/stream.cpp new file mode 100644 index 0000000..b534b46 --- /dev/null +++ b/HIP/hipStreams/stream.cpp @@ -0,0 +1,138 @@ +/* +Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <iostream> +#include <hip/hip_runtime.h> + +#define WIDTH 32 + +#define NUM (WIDTH * WIDTH) + +#define THREADS_PER_BLOCK_X 4 +#define THREADS_PER_BLOCK_Y 4 +#define THREADS_PER_BLOCK_Z 1 + +using namespace std; + +__global__ void matrixTranspose_static_shared(float* out, float* in, + const int width) { + __shared__ float sharedMem[WIDTH * WIDTH]; + + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + + sharedMem[y * width + x] = in[x * width + y]; + + __syncthreads(); + + out[y * width + x] = sharedMem[y * width + x]; +} + +__global__ void matrixTranspose_dynamic_shared(float* out, float* in, + const int width) { + extern __shared__ float sharedMem[]; + + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + + sharedMem[y * width + x] = in[x * width + y]; + + __syncthreads(); + + out[y * width + x] = sharedMem[y * width + x]; +} + +void MultipleStream(float** data, float* randArray, float** gpuTransposeMatrix, + float** TransposeMatrix, int width) { + const int num_streams = 2; + hipStream_t streams[num_streams]; + + for (int i = 0; i < num_streams; i++) hipStreamCreate(&streams[i]); + + for (int i = 0; i < num_streams; i++) { + hipMalloc((void**)&data[i], NUM * sizeof(float)); + hipMemcpyAsync(data[i], randArray, NUM * sizeof(float), hipMemcpyHostToDevice, streams[i]); + } + + hipLaunchKernelGGL(matrixTranspose_static_shared, + dim3(WIDTH / THREADS_PER_BLOCK_X, WIDTH / THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), 0, streams[0], + gpuTransposeMatrix[0], data[0], width); + + hipLaunchKernelGGL(matrixTranspose_dynamic_shared, + dim3(WIDTH / THREADS_PER_BLOCK_X, WIDTH / THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), sizeof(float) * WIDTH * WIDTH, + streams[1], gpuTransposeMatrix[1], data[1], width); + + for (int i = 0; i < num_streams; i++) + hipMemcpyAsync(TransposeMatrix[i], gpuTransposeMatrix[i], NUM * sizeof(float), + hipMemcpyDeviceToHost, streams[i]); +} + +int main() { + hipSetDevice(0); + + float *data[2], *TransposeMatrix[2], *gpuTransposeMatrix[2], *randArray; + + int width = WIDTH; + + randArray = (float*)malloc(NUM * sizeof(float)); + + TransposeMatrix[0] = (float*)malloc(NUM * sizeof(float)); + TransposeMatrix[1] = (float*)malloc(NUM * sizeof(float)); + + hipMalloc((void**)&gpuTransposeMatrix[0], NUM * sizeof(float)); + hipMalloc((void**)&gpuTransposeMatrix[1], NUM * sizeof(float)); + + for (int i = 0; i < NUM; i++) { + randArray[i] = (float)i * 1.0f; + } + + MultipleStream(data, randArray, gpuTransposeMatrix, TransposeMatrix, width); + + hipDeviceSynchronize(); + + // verify the results + int errors = 0; + double eps = 1.0E-6; + for (int i = 0; i < NUM; i++) { + if (std::abs(TransposeMatrix[0][i] - TransposeMatrix[1][i]) > eps) { + printf("%d stream0: %f stream1 %f\n", i, TransposeMatrix[0][i], TransposeMatrix[1][i]); + errors++; + } + } + if (errors != 0) { + printf("FAILED: %d errors\n", errors); + } else { + printf("stream PASSED!\n"); + } + + free(randArray); + for (int i = 0; i < 2; i++) { + hipFree(data[i]); + hipFree(gpuTransposeMatrix[i]); + free(TransposeMatrix[i]); + } + + hipDeviceReset(); + return 0; +} -- GitLab From e79e5675f731869fa435e9e88351306d4144d86f Mon Sep 17 00:00:00 2001 From: Umesh Seth <umeshseth@login2.crusher.olcf.ornl.gov> Date: Wed, 2 Nov 2022 04:33:15 -0400 Subject: [PATCH 6/9] adds dynamic sharedMem example --- HIP/dynamic_sharedMem/CMakeLists.txt | 43 ++++++++ HIP/dynamic_sharedMem/Makefile | 57 ++++++++++ HIP/dynamic_sharedMem/Readme.md | 52 +++++++++ HIP/dynamic_sharedMem/dynamic_shared | Bin 0 -> 112584 bytes HIP/dynamic_sharedMem/dynamic_shared.cpp | 127 ++++++++++++++++++++++ HIP/dynamic_sharedMem/dynamic_shared.o | Bin 0 -> 114120 bytes HIP/static_sharedMem/CMakeLists.txt | 44 ++++++++ HIP/static_sharedMem/Makefile | 57 ++++++++++ HIP/static_sharedMem/Readme.md | 42 ++++++++ HIP/static_sharedMem/sharedMemory.cpp | 128 +++++++++++++++++++++++ 10 files changed, 550 insertions(+) create mode 100644 HIP/dynamic_sharedMem/CMakeLists.txt create mode 100644 HIP/dynamic_sharedMem/Makefile create mode 100644 HIP/dynamic_sharedMem/Readme.md create mode 100755 HIP/dynamic_sharedMem/dynamic_shared create mode 100644 HIP/dynamic_sharedMem/dynamic_shared.cpp create mode 100644 HIP/dynamic_sharedMem/dynamic_shared.o create mode 100644 HIP/static_sharedMem/CMakeLists.txt create mode 100644 HIP/static_sharedMem/Makefile create mode 100644 HIP/static_sharedMem/Readme.md create mode 100644 HIP/static_sharedMem/sharedMemory.cpp diff --git a/HIP/dynamic_sharedMem/CMakeLists.txt b/HIP/dynamic_sharedMem/CMakeLists.txt new file mode 100644 index 0000000..73c4fe6 --- /dev/null +++ b/HIP/dynamic_sharedMem/CMakeLists.txt @@ -0,0 +1,43 @@ +# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +project(dynamic_shared) + +cmake_minimum_required(VERSION 3.10) + +if (NOT DEFINED ROCM_PATH ) + set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) +endif () + +# Search for rocm in common locations +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) + +# Find hip +find_package(hip) + +# Set compiler and linker +set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) + +# Create the excutable +add_executable(dynamic_shared dynamic_shared.cpp) + +# Link with HIP +target_link_libraries(dynamic_shared hip::host) diff --git a/HIP/dynamic_sharedMem/Makefile b/HIP/dynamic_sharedMem/Makefile new file mode 100644 index 0000000..71d4f13 --- /dev/null +++ b/HIP/dynamic_sharedMem/Makefile @@ -0,0 +1,57 @@ +# Copyright (c) 2016 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ROCM_PATH?= $(wildcard /opt/rocm/) +HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) +ifeq (,$(HIP_PATH)) + HIP_PATH=../../.. +endif + +HIPCC=$(HIP_PATH)/bin/hipcc + +TARGET=hcc + +SOURCES = dynamic_shared.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +EXECUTABLE=./dynamic_shared + +.PHONY: test + + +all: $(EXECUTABLE) test + +CXXFLAGS =-g +CXX=$(HIPCC) + + +$(EXECUTABLE): $(OBJECTS) + $(HIPCC) $(OBJECTS) -o $@ + + +test: $(EXECUTABLE) + $(EXECUTABLE) + + +clean: + rm -f $(EXECUTABLE) + rm -f $(OBJECTS) + rm -f $(HIP_PATH)/src/*.o + diff --git a/HIP/dynamic_sharedMem/Readme.md b/HIP/dynamic_sharedMem/Readme.md new file mode 100644 index 0000000..02a8cb3 --- /dev/null +++ b/HIP/dynamic_sharedMem/Readme.md @@ -0,0 +1,52 @@ +## Using Dynamic shared memory ### + +Earlier we learned how to use static shared memory. In this tutorial, we'll explain how to use the dynamic version of shared memory to improve the performance. + +## Introduction: + +As we mentioned earlier that Memory bottlenecks is the main problem why we are not able to get the highest performance, therefore minimizing the latency for memory access plays prominent role in application optimization. In this tutorial, we'll learn how to use dynamic shared memory. + +## Requirement: +For hardware requirement and software installation [Installation](https://github.com/ROCm-Developer-Tools/HIP/blob/master/INSTALL.md) + +## prerequiste knowledge: + +Programmers familiar with CUDA, OpenCL will be able to quickly learn and start coding with the HIP API. In case you are not, don't worry. You choose to start with the best one. We'll be explaining everything assuming you are completely new to gpgpu programming. + +## Simple Matrix Transpose + +We will be using the Simple Matrix Transpose application from the previous tutorial and modify it to learn how to use shared memory. + +## Shared Memory + +Shared memory is way more faster than that of global and constant memory and accessible to all the threads in the block. + +Previously, it was essential to declare dynamic shared memory using the HIP_DYNAMIC_SHARED macro for accuracy, as using static shared memory in the same kernel could result in overlapping memory ranges and data-races. + +Now, the HIP-Clang compiler provides support for extern shared declarations, and the HIP_DYNAMIC_SHARED option is no longer required. You may use the standard extern definition: +extern __shared__ type var[]; + + +The other important change is: +``` + hipLaunchKernelGGL(matrixTranspose, + dim3(WIDTH/THREADS_PER_BLOCK_X, WIDTH/THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), + sizeof(float)*WIDTH*WIDTH, 0, + gpuTransposeMatrix , gpuMatrix, WIDTH); +``` +here we replaced 4th parameter with amount of additional shared memory to allocate when launching the kernel. + +## How to build and run: +Use the make command and execute it using ./exe +Use hipcc to build the application, which is using hcc on AMD and nvcc on nvidia. + +## More Info: +- [HIP FAQ](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_faq.md) +- [HIP Kernel Language](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_kernel_language.md) +- [HIP Runtime API (Doxygen)](http://rocm-developer-tools.github.io/HIP) +- [HIP Porting Guide](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_porting_guide.md) +- [HIP Terminology](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_terms.md) (including Rosetta Stone of GPU computing terms across CUDA/HIP/HC/AMP/OpenL) +- [HIPIFY](https://github.com/ROCm-Developer-Tools/HIPIFY/blob/master/README.md) +- [Developer/CONTRIBUTING Info](https://github.com/ROCm-Developer-Tools/HIP/blob/master/CONTRIBUTING.md) +- [Release Notes](https://github.com/ROCm-Developer-Tools/HIP/blob/master/RELEASE.md) diff --git a/HIP/dynamic_sharedMem/dynamic_shared b/HIP/dynamic_sharedMem/dynamic_shared new file mode 100755 index 0000000000000000000000000000000000000000..5b7831ce863ff64848a339adc34cd02a5f3cad06 GIT binary patch literal 112584 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 literal 0 HcmV?d00001 diff --git a/HIP/dynamic_sharedMem/dynamic_shared.cpp b/HIP/dynamic_sharedMem/dynamic_shared.cpp new file mode 100644 index 0000000..3e1c0f4 --- /dev/null +++ b/HIP/dynamic_sharedMem/dynamic_shared.cpp @@ -0,0 +1,127 @@ +/* +Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <iostream> + +// hip header file +#include "hip/hip_runtime.h" + +#define WIDTH 16 + +#define NUM (WIDTH * WIDTH) + +#define THREADS_PER_BLOCK_X 4 +#define THREADS_PER_BLOCK_Y 4 +#define THREADS_PER_BLOCK_Z 1 + +// Device (Kernel) function, it must be void +__global__ void matrixTranspose(float* out, float* in, const int width) { + extern __shared__ float sharedMem[]; + + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + + sharedMem[y * width + x] = in[x * width + y]; + + __syncthreads(); + + out[y * width + x] = sharedMem[y * width + x]; +} + +// CPU implementation of matrix transpose +void matrixTransposeCPUReference(float* output, float* input, const unsigned int width) { + for (unsigned int j = 0; j < width; j++) { + for (unsigned int i = 0; i < width; i++) { + output[i * width + j] = input[j * width + i]; + } + } +} + +int main() { + float* Matrix; + float* TransposeMatrix; + float* cpuTransposeMatrix; + + float* gpuMatrix; + float* gpuTransposeMatrix; + + hipDeviceProp_t devProp; + hipGetDeviceProperties(&devProp, 0); + + std::cout << "Device name " << devProp.name << std::endl; + + int i; + int errors; + + Matrix = (float*)malloc(NUM * sizeof(float)); + TransposeMatrix = (float*)malloc(NUM * sizeof(float)); + cpuTransposeMatrix = (float*)malloc(NUM * sizeof(float)); + + // initialize the input data + for (i = 0; i < NUM; i++) { + Matrix[i] = (float)i * 10.0f; + } + + // allocate the memory on the device side + hipMalloc((void**)&gpuMatrix, NUM * sizeof(float)); + hipMalloc((void**)&gpuTransposeMatrix, NUM * sizeof(float)); + + // Memory transfer from host to device + hipMemcpy(gpuMatrix, Matrix, NUM * sizeof(float), hipMemcpyHostToDevice); + + // Lauching kernel from host + hipLaunchKernelGGL(matrixTranspose, dim3(WIDTH / THREADS_PER_BLOCK_X, WIDTH / THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), sizeof(float) * WIDTH * WIDTH, + 0, gpuTransposeMatrix, gpuMatrix, WIDTH); + + // Memory transfer from device to host + hipMemcpy(TransposeMatrix, gpuTransposeMatrix, NUM * sizeof(float), hipMemcpyDeviceToHost); + + // CPU MatrixTranspose computation + matrixTransposeCPUReference(cpuTransposeMatrix, Matrix, WIDTH); + + // verify the results + errors = 0; + double eps = 1.0E-6; + for (i = 0; i < NUM; i++) { + if (std::abs(TransposeMatrix[i] - cpuTransposeMatrix[i]) > eps) { + printf("%d cpu: %f gpu %f\n", i, cpuTransposeMatrix[i], TransposeMatrix[i]); + errors++; + } + } + if (errors != 0) { + printf("FAILED: %d errors\n", errors); + } else { + printf("dynamic_shared PASSED!\n"); + } + + // free the resources on device side + hipFree(gpuMatrix); + hipFree(gpuTransposeMatrix); + + // free the resources on host side + free(Matrix); + free(TransposeMatrix); + free(cpuTransposeMatrix); + + return errors; +} diff --git a/HIP/dynamic_sharedMem/dynamic_shared.o b/HIP/dynamic_sharedMem/dynamic_shared.o new file mode 100644 index 0000000000000000000000000000000000000000..5b5da898ec3f25300cc31c5866b12b7b48fe8c6c GIT binary patch literal 114120 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�OL4)9OH#L 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 J;GgIJ{{XaXiCzEz literal 0 HcmV?d00001 diff --git a/HIP/static_sharedMem/CMakeLists.txt b/HIP/static_sharedMem/CMakeLists.txt new file mode 100644 index 0000000..f2f5196 --- /dev/null +++ b/HIP/static_sharedMem/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +project(sharedMemory) + +cmake_minimum_required(VERSION 3.10) + +if (NOT DEFINED ROCM_PATH ) + set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) +endif () + +# Search for rocm in common locations +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) + +# Find hip +find_package(hip) + +# Set compiler and linker +set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_BUILD_TYPE Release) + +# Create the excutable +add_executable(sharedMemory sharedMemory.cpp) + +# Link with HIP +target_link_libraries(sharedMemory hip::host) diff --git a/HIP/static_sharedMem/Makefile b/HIP/static_sharedMem/Makefile new file mode 100644 index 0000000..ef8727c --- /dev/null +++ b/HIP/static_sharedMem/Makefile @@ -0,0 +1,57 @@ +# Copyright (c) 2016 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ROCM_PATH?= $(wildcard /opt/rocm/) +HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) +ifeq (,$(HIP_PATH)) + HIP_PATH=../../.. +endif + +HIPCC=$(HIP_PATH)/bin/hipcc + +TARGET=hcc + +SOURCES = sharedMemory.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +EXECUTABLE=./sharedMemory + +.PHONY: test + + +all: $(EXECUTABLE) test + +CXXFLAGS =-g +CXX=$(HIPCC) + + +$(EXECUTABLE): $(OBJECTS) + $(HIPCC) $(OBJECTS) -o $@ + + +test: $(EXECUTABLE) + $(EXECUTABLE) + + +clean: + rm -f $(EXECUTABLE) + rm -f $(OBJECTS) + rm -f $(HIP_PATH)/src/*.o + diff --git a/HIP/static_sharedMem/Readme.md b/HIP/static_sharedMem/Readme.md new file mode 100644 index 0000000..756cb6e --- /dev/null +++ b/HIP/static_sharedMem/Readme.md @@ -0,0 +1,42 @@ +## Using shared memory ### + +Earlier we learned how to write our first hip program, in which we compute Matrix Transpose. In this tutorial, we'll explain how to use the shared memory to improve the performance. + +## Introduction: + +As we mentioned earlier that Memory bottlenecks is the main problem why we are not able to get the highest performance, therefore minimizing the latency for memory access plays prominent role in application optimization. In this tutorial, we'll learn how to use static shared memory and will explain the dynamic one latter. + +## Requirement: +For hardware requirement and software installation [Installation](https://github.com/ROCm-Developer-Tools/HIP/blob/master/INSTALL.md) + +## prerequiste knowledge: + +Programmers familiar with CUDA, OpenCL will be able to quickly learn and start coding with the HIP API. In case you are not, don't worry. You choose to start with the best one. We'll be explaining everything assuming you are completely new to gpgpu programming. + +## Simple Matrix Transpose + +We will be using the Simple Matrix Transpose application from the previous tutorial and modify it to learn how to use shared memory. + +## Shared Memory + +Shared memory is way more faster than that of global and constant memory and accessible to all the threads in the block. If the size of shared memory is known at compile time, we can specify the size and will use the static shared memory. In the same sourcecode, we will use the `__shared__` variable type qualifier as follows: + +` __shared__ float sharedMem[1024*1024];` + +Be careful while using shared memory, since all threads within the block can access the shared memory, we need to sync the operation of individual threads by using: + +` __syncthreads();` + +## How to build and run: +Use the make command and execute it using ./exe +Use hipcc to build the application, which is using hcc on AMD and nvcc on nvidia. + +## More Info: +- [HIP FAQ](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_faq.md) +- [HIP Kernel Language](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_kernel_language.md) +- [HIP Runtime API (Doxygen)](http://rocm-developer-tools.github.io/HIP) +- [HIP Porting Guide](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_porting_guide.md) +- [HIP Terminology](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_terms.md) (including Rosetta Stone of GPU computing terms across CUDA/HIP/HC/AMP/OpenL) +- [HIPIFY](https://github.com/ROCm-Developer-Tools/HIPIFY/blob/master/README.md) +- [Developer/CONTRIBUTING Info](https://github.com/ROCm-Developer-Tools/HIP/blob/master/CONTRIBUTING.md) +- [Release Notes](https://github.com/ROCm-Developer-Tools/HIP/blob/master/RELEASE.md) diff --git a/HIP/static_sharedMem/sharedMemory.cpp b/HIP/static_sharedMem/sharedMemory.cpp new file mode 100644 index 0000000..cff03f0 --- /dev/null +++ b/HIP/static_sharedMem/sharedMemory.cpp @@ -0,0 +1,128 @@ +/* +Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <iostream> + +// hip header file +#include "hip/hip_runtime.h" + + +#define WIDTH 64 + +#define NUM (WIDTH * WIDTH) + +#define THREADS_PER_BLOCK_X 4 +#define THREADS_PER_BLOCK_Y 4 +#define THREADS_PER_BLOCK_Z 1 + +// Device (Kernel) function, it must be void +__global__ void matrixTranspose(float* out, float* in, const int width) { + __shared__ float sharedMem[WIDTH * WIDTH]; + + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + + sharedMem[y * width + x] = in[x * width + y]; + + __syncthreads(); + + out[y * width + x] = sharedMem[y * width + x]; +} + +// CPU implementation of matrix transpose +void matrixTransposeCPUReference(float* output, float* input, const unsigned int width) { + for (unsigned int j = 0; j < width; j++) { + for (unsigned int i = 0; i < width; i++) { + output[i * width + j] = input[j * width + i]; + } + } +} + +int main() { + float* Matrix; + float* TransposeMatrix; + float* cpuTransposeMatrix; + + float* gpuMatrix; + float* gpuTransposeMatrix; + + hipDeviceProp_t devProp; + hipGetDeviceProperties(&devProp, 0); + + std::cout << "Device name " << devProp.name << std::endl; + + int i; + int errors; + + Matrix = (float*)malloc(NUM * sizeof(float)); + TransposeMatrix = (float*)malloc(NUM * sizeof(float)); + cpuTransposeMatrix = (float*)malloc(NUM * sizeof(float)); + + // initialize the input data + for (i = 0; i < NUM; i++) { + Matrix[i] = (float)i * 10.0f; + } + + // allocate the memory on the device side + hipMalloc((void**)&gpuMatrix, NUM * sizeof(float)); + hipMalloc((void**)&gpuTransposeMatrix, NUM * sizeof(float)); + + // Memory transfer from host to device + hipMemcpy(gpuMatrix, Matrix, NUM * sizeof(float), hipMemcpyHostToDevice); + + // Lauching kernel from host + hipLaunchKernelGGL(matrixTranspose, dim3(WIDTH / THREADS_PER_BLOCK_X, WIDTH / THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), 0, 0, gpuTransposeMatrix, + gpuMatrix, WIDTH); + + // Memory transfer from device to host + hipMemcpy(TransposeMatrix, gpuTransposeMatrix, NUM * sizeof(float), hipMemcpyDeviceToHost); + + // CPU MatrixTranspose computation + matrixTransposeCPUReference(cpuTransposeMatrix, Matrix, WIDTH); + + // verify the results + errors = 0; + double eps = 1.0E-6; + for (i = 0; i < NUM; i++) { + if (std::abs(TransposeMatrix[i] - cpuTransposeMatrix[i]) > eps) { + printf("%d cpu: %f gpu %f\n", i, cpuTransposeMatrix[i], TransposeMatrix[i]); + errors++; + } + } + if (errors != 0) { + printf("FAILED: %d errors\n", errors); + } else { + printf("PASSED!\n"); + } + + // free the resources on device side + hipFree(gpuMatrix); + hipFree(gpuTransposeMatrix); + + // free the resources on host side + free(Matrix); + free(TransposeMatrix); + free(cpuTransposeMatrix); + + return errors; +} -- GitLab From 3ac15afbddd655acf515aa4f24910d22b53a0e0a Mon Sep 17 00:00:00 2001 From: Umesh Seth <umeshseth@login2.crusher.olcf.ornl.gov> Date: Wed, 2 Nov 2022 04:36:17 -0400 Subject: [PATCH 7/9] minor modifs --- HIP/dynamic_sharedMem/dynamic_shared | Bin 112584 -> 0 bytes HIP/dynamic_sharedMem/dynamic_shared.o | Bin 114120 -> 0 bytes HIP/shared_memory/CMakeLists.txt | 44 --------- HIP/shared_memory/Makefile | 57 ----------- HIP/shared_memory/Readme.md | 42 -------- HIP/shared_memory/sharedMemory.cpp | 128 ------------------------- 6 files changed, 271 deletions(-) delete mode 100755 HIP/dynamic_sharedMem/dynamic_shared delete mode 100644 HIP/dynamic_sharedMem/dynamic_shared.o delete mode 100644 HIP/shared_memory/CMakeLists.txt delete mode 100644 HIP/shared_memory/Makefile delete mode 100644 HIP/shared_memory/Readme.md delete mode 100644 HIP/shared_memory/sharedMemory.cpp diff --git a/HIP/dynamic_sharedMem/dynamic_shared b/HIP/dynamic_sharedMem/dynamic_shared deleted file mode 100755 index 5b7831ce863ff64848a339adc34cd02a5f3cad06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 112584 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 diff --git a/HIP/dynamic_sharedMem/dynamic_shared.o b/HIP/dynamic_sharedMem/dynamic_shared.o deleted file mode 100644 index 5b5da898ec3f25300cc31c5866b12b7b48fe8c6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114120 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�OL4)9OH#L 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 J;GgIJ{{XaXiCzEz diff --git a/HIP/shared_memory/CMakeLists.txt b/HIP/shared_memory/CMakeLists.txt deleted file mode 100644 index f2f5196..0000000 --- a/HIP/shared_memory/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -project(sharedMemory) - -cmake_minimum_required(VERSION 3.10) - -if (NOT DEFINED ROCM_PATH ) - set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) -endif () - -# Search for rocm in common locations -list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) - -# Find hip -find_package(hip) - -# Set compiler and linker -set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) -set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) -set(CMAKE_BUILD_TYPE Release) - -# Create the excutable -add_executable(sharedMemory sharedMemory.cpp) - -# Link with HIP -target_link_libraries(sharedMemory hip::host) diff --git a/HIP/shared_memory/Makefile b/HIP/shared_memory/Makefile deleted file mode 100644 index ef8727c..0000000 --- a/HIP/shared_memory/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2016 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -ROCM_PATH?= $(wildcard /opt/rocm/) -HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) -ifeq (,$(HIP_PATH)) - HIP_PATH=../../.. -endif - -HIPCC=$(HIP_PATH)/bin/hipcc - -TARGET=hcc - -SOURCES = sharedMemory.cpp -OBJECTS = $(SOURCES:.cpp=.o) - -EXECUTABLE=./sharedMemory - -.PHONY: test - - -all: $(EXECUTABLE) test - -CXXFLAGS =-g -CXX=$(HIPCC) - - -$(EXECUTABLE): $(OBJECTS) - $(HIPCC) $(OBJECTS) -o $@ - - -test: $(EXECUTABLE) - $(EXECUTABLE) - - -clean: - rm -f $(EXECUTABLE) - rm -f $(OBJECTS) - rm -f $(HIP_PATH)/src/*.o - diff --git a/HIP/shared_memory/Readme.md b/HIP/shared_memory/Readme.md deleted file mode 100644 index 756cb6e..0000000 --- a/HIP/shared_memory/Readme.md +++ /dev/null @@ -1,42 +0,0 @@ -## Using shared memory ### - -Earlier we learned how to write our first hip program, in which we compute Matrix Transpose. In this tutorial, we'll explain how to use the shared memory to improve the performance. - -## Introduction: - -As we mentioned earlier that Memory bottlenecks is the main problem why we are not able to get the highest performance, therefore minimizing the latency for memory access plays prominent role in application optimization. In this tutorial, we'll learn how to use static shared memory and will explain the dynamic one latter. - -## Requirement: -For hardware requirement and software installation [Installation](https://github.com/ROCm-Developer-Tools/HIP/blob/master/INSTALL.md) - -## prerequiste knowledge: - -Programmers familiar with CUDA, OpenCL will be able to quickly learn and start coding with the HIP API. In case you are not, don't worry. You choose to start with the best one. We'll be explaining everything assuming you are completely new to gpgpu programming. - -## Simple Matrix Transpose - -We will be using the Simple Matrix Transpose application from the previous tutorial and modify it to learn how to use shared memory. - -## Shared Memory - -Shared memory is way more faster than that of global and constant memory and accessible to all the threads in the block. If the size of shared memory is known at compile time, we can specify the size and will use the static shared memory. In the same sourcecode, we will use the `__shared__` variable type qualifier as follows: - -` __shared__ float sharedMem[1024*1024];` - -Be careful while using shared memory, since all threads within the block can access the shared memory, we need to sync the operation of individual threads by using: - -` __syncthreads();` - -## How to build and run: -Use the make command and execute it using ./exe -Use hipcc to build the application, which is using hcc on AMD and nvcc on nvidia. - -## More Info: -- [HIP FAQ](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_faq.md) -- [HIP Kernel Language](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_kernel_language.md) -- [HIP Runtime API (Doxygen)](http://rocm-developer-tools.github.io/HIP) -- [HIP Porting Guide](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_porting_guide.md) -- [HIP Terminology](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_terms.md) (including Rosetta Stone of GPU computing terms across CUDA/HIP/HC/AMP/OpenL) -- [HIPIFY](https://github.com/ROCm-Developer-Tools/HIPIFY/blob/master/README.md) -- [Developer/CONTRIBUTING Info](https://github.com/ROCm-Developer-Tools/HIP/blob/master/CONTRIBUTING.md) -- [Release Notes](https://github.com/ROCm-Developer-Tools/HIP/blob/master/RELEASE.md) diff --git a/HIP/shared_memory/sharedMemory.cpp b/HIP/shared_memory/sharedMemory.cpp deleted file mode 100644 index cff03f0..0000000 --- a/HIP/shared_memory/sharedMemory.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* -Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <iostream> - -// hip header file -#include "hip/hip_runtime.h" - - -#define WIDTH 64 - -#define NUM (WIDTH * WIDTH) - -#define THREADS_PER_BLOCK_X 4 -#define THREADS_PER_BLOCK_Y 4 -#define THREADS_PER_BLOCK_Z 1 - -// Device (Kernel) function, it must be void -__global__ void matrixTranspose(float* out, float* in, const int width) { - __shared__ float sharedMem[WIDTH * WIDTH]; - - int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; - int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; - - sharedMem[y * width + x] = in[x * width + y]; - - __syncthreads(); - - out[y * width + x] = sharedMem[y * width + x]; -} - -// CPU implementation of matrix transpose -void matrixTransposeCPUReference(float* output, float* input, const unsigned int width) { - for (unsigned int j = 0; j < width; j++) { - for (unsigned int i = 0; i < width; i++) { - output[i * width + j] = input[j * width + i]; - } - } -} - -int main() { - float* Matrix; - float* TransposeMatrix; - float* cpuTransposeMatrix; - - float* gpuMatrix; - float* gpuTransposeMatrix; - - hipDeviceProp_t devProp; - hipGetDeviceProperties(&devProp, 0); - - std::cout << "Device name " << devProp.name << std::endl; - - int i; - int errors; - - Matrix = (float*)malloc(NUM * sizeof(float)); - TransposeMatrix = (float*)malloc(NUM * sizeof(float)); - cpuTransposeMatrix = (float*)malloc(NUM * sizeof(float)); - - // initialize the input data - for (i = 0; i < NUM; i++) { - Matrix[i] = (float)i * 10.0f; - } - - // allocate the memory on the device side - hipMalloc((void**)&gpuMatrix, NUM * sizeof(float)); - hipMalloc((void**)&gpuTransposeMatrix, NUM * sizeof(float)); - - // Memory transfer from host to device - hipMemcpy(gpuMatrix, Matrix, NUM * sizeof(float), hipMemcpyHostToDevice); - - // Lauching kernel from host - hipLaunchKernelGGL(matrixTranspose, dim3(WIDTH / THREADS_PER_BLOCK_X, WIDTH / THREADS_PER_BLOCK_Y), - dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), 0, 0, gpuTransposeMatrix, - gpuMatrix, WIDTH); - - // Memory transfer from device to host - hipMemcpy(TransposeMatrix, gpuTransposeMatrix, NUM * sizeof(float), hipMemcpyDeviceToHost); - - // CPU MatrixTranspose computation - matrixTransposeCPUReference(cpuTransposeMatrix, Matrix, WIDTH); - - // verify the results - errors = 0; - double eps = 1.0E-6; - for (i = 0; i < NUM; i++) { - if (std::abs(TransposeMatrix[i] - cpuTransposeMatrix[i]) > eps) { - printf("%d cpu: %f gpu %f\n", i, cpuTransposeMatrix[i], TransposeMatrix[i]); - errors++; - } - } - if (errors != 0) { - printf("FAILED: %d errors\n", errors); - } else { - printf("PASSED!\n"); - } - - // free the resources on device side - hipFree(gpuMatrix); - hipFree(gpuTransposeMatrix); - - // free the resources on host side - free(Matrix); - free(TransposeMatrix); - free(cpuTransposeMatrix); - - return errors; -} -- GitLab From da1f8ff0f98c3fa464ff4d74777477fe11c813bf Mon Sep 17 00:00:00 2001 From: Umesh Seth <umeshseth@login2.crusher.olcf.ornl.gov> Date: Wed, 2 Nov 2022 05:02:32 -0400 Subject: [PATCH 8/9] adds shfl examples --- HIP/2dshfl/2dshfl.cpp | 122 +++++++++++++++++++++++++++++++++++++ HIP/2dshfl/CMakeLists.txt | 43 +++++++++++++ HIP/2dshfl/Makefile | 61 +++++++++++++++++++ HIP/2dshfl/Readme.md | 55 +++++++++++++++++ HIP/shfl/CMakeLists.txt | 44 ++++++++++++++ HIP/shfl/Makefile | 60 ++++++++++++++++++ HIP/shfl/Readme.md | 53 ++++++++++++++++ HIP/shfl/shfl.cpp | 124 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 562 insertions(+) create mode 100644 HIP/2dshfl/2dshfl.cpp create mode 100644 HIP/2dshfl/CMakeLists.txt create mode 100644 HIP/2dshfl/Makefile create mode 100644 HIP/2dshfl/Readme.md create mode 100644 HIP/shfl/CMakeLists.txt create mode 100644 HIP/shfl/Makefile create mode 100644 HIP/shfl/Readme.md create mode 100644 HIP/shfl/shfl.cpp diff --git a/HIP/2dshfl/2dshfl.cpp b/HIP/2dshfl/2dshfl.cpp new file mode 100644 index 0000000..d2c26e7 --- /dev/null +++ b/HIP/2dshfl/2dshfl.cpp @@ -0,0 +1,122 @@ +/* +Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <iostream> + +// hip header file +#include "hip/hip_runtime.h" + + +#define WIDTH 4 + +#define NUM (WIDTH * WIDTH) + +#define THREADS_PER_BLOCK_X 4 +#define THREADS_PER_BLOCK_Y 4 +#define THREADS_PER_BLOCK_Z 1 + +// Device (Kernel) function, it must be void +__global__ void matrixTranspose(float* out, float* in, const int width) { + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + float val = in[y * width + x]; + + out[x * width + y] = __shfl(val, y * width + x); +} + +// CPU implementation of matrix transpose +void matrixTransposeCPUReference(float* output, float* input, const unsigned int width) { + for (unsigned int j = 0; j < width; j++) { + for (unsigned int i = 0; i < width; i++) { + output[i * width + j] = input[j * width + i]; + } + } +} + +int main() { + float* Matrix; + float* TransposeMatrix; + float* cpuTransposeMatrix; + + float* gpuMatrix; + float* gpuTransposeMatrix; + + hipDeviceProp_t devProp; + hipGetDeviceProperties(&devProp, 0); + + std::cout << "Device name " << devProp.name << std::endl; + + int i; + int errors; + + Matrix = (float*)malloc(NUM * sizeof(float)); + TransposeMatrix = (float*)malloc(NUM * sizeof(float)); + cpuTransposeMatrix = (float*)malloc(NUM * sizeof(float)); + + // initialize the input data + for (i = 0; i < NUM; i++) { + Matrix[i] = (float)i * 10.0f; + } + + // allocate the memory on the device side + hipMalloc((void**)&gpuMatrix, NUM * sizeof(float)); + hipMalloc((void**)&gpuTransposeMatrix, NUM * sizeof(float)); + + // Memory transfer from host to device + hipMemcpy(gpuMatrix, Matrix, NUM * sizeof(float), hipMemcpyHostToDevice); + + // Lauching kernel from host + hipLaunchKernelGGL(matrixTranspose, dim3(1), dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), 0, 0, + gpuTransposeMatrix, gpuMatrix, WIDTH); + + // Memory transfer from device to host + hipMemcpy(TransposeMatrix, gpuTransposeMatrix, NUM * sizeof(float), hipMemcpyDeviceToHost); + + // CPU MatrixTranspose computation + matrixTransposeCPUReference(cpuTransposeMatrix, Matrix, WIDTH); + + // verify the results + errors = 0; + double eps = 1.0E-6; + for (i = 0; i < NUM; i++) { + if (std::abs(TransposeMatrix[i] - cpuTransposeMatrix[i]) > eps) { + printf("%d cpu: %f gpu %f\n", i, cpuTransposeMatrix[i], TransposeMatrix[i]); + errors++; + } + } + if (errors != 0) { + printf("FAILED: %d errors\n", errors); + } else { + printf("PASSED!\n"); + } + + // free the resources on device side + hipFree(gpuMatrix); + hipFree(gpuTransposeMatrix); + + // free the resources on host side + free(Matrix); + free(TransposeMatrix); + free(cpuTransposeMatrix); + + return errors; +} diff --git a/HIP/2dshfl/CMakeLists.txt b/HIP/2dshfl/CMakeLists.txt new file mode 100644 index 0000000..d0ab528 --- /dev/null +++ b/HIP/2dshfl/CMakeLists.txt @@ -0,0 +1,43 @@ +# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +project(2dshfl) + +cmake_minimum_required(VERSION 3.10) + +if (NOT DEFINED ROCM_PATH ) + set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) +endif () + +# Search for rocm in common locations +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) + +# Find hip +find_package(hip) + +# Set compiler and linker +set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) + +# Create the excutable +add_executable(2dshfl 2dshfl.cpp) + +# Link with HIP +target_link_libraries(2dshfl hip::host) diff --git a/HIP/2dshfl/Makefile b/HIP/2dshfl/Makefile new file mode 100644 index 0000000..5724069 --- /dev/null +++ b/HIP/2dshfl/Makefile @@ -0,0 +1,61 @@ +# Copyright (c) 2016 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ROCM_PATH?= $(wildcard /opt/rocm/) +HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) +ifeq (,$(HIP_PATH)) + HIP_PATH=../../.. +endif + +ifeq (gfx701, $(findstring gfx701,$(HCC_AMDGPU_TARGET))) + $(error gfx701 is not a supported device for this sample) +endif + +HIPCC=$(HIP_PATH)/bin/hipcc + +TARGET=hcc + +SOURCES = 2dshfl.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +EXECUTABLE=./2dshfl + +.PHONY: test + + +all: $(EXECUTABLE) test + +CXXFLAGS =-g +CXX=$(HIPCC) + + +$(EXECUTABLE): $(OBJECTS) + $(HIPCC) $(OBJECTS) -o $@ + + +test: $(EXECUTABLE) + $(EXECUTABLE) + + +clean: + rm -f $(EXECUTABLE) + rm -f $(OBJECTS) + rm -f $(HIP_PATH)/src/*.o + diff --git a/HIP/2dshfl/Readme.md b/HIP/2dshfl/Readme.md new file mode 100644 index 0000000..fa10c71 --- /dev/null +++ b/HIP/2dshfl/Readme.md @@ -0,0 +1,55 @@ +## Warp shfl operations in 2D ### + +This tutorial is follow-up of the previous tutorial, where we learned how to use shfl ops. In this tutorial, we'll explain how to scale similar kind of operations to multi-dimensional space by using previous tutorial source-code. + +## Introduction: + +Let's talk about Warp first. The kernel code is executed in groups of fixed number of threads known as Warp. For nvidia WarpSize is 32 while for AMD, 32 for Polaris architecture and 64 for rest. Threads in a warp are referred to as lanes and are numbered from 0 to warpSize -1. With the help of shfl ops, we can directly exchange values of variable between threads without using any memory ops within a warp. There are four types of shfl ops: +``` + int __shfl (int var, int srcLane, int width=warpSize); + float __shfl (float var, int srcLane, int width=warpSize); + int __shfl_up (int var, unsigned int delta, int width=warpSize); + float __shfl_up (float var, unsigned int delta, int width=warpSize); + int __shfl_down (int var, unsigned int delta, int width=warpSize); + float __shfl_down (float var, unsigned int delta, int width=warpSize); + int __shfl_xor (int var, int laneMask, int width=warpSize); + float __shfl_xor (float var, int laneMask, int width=warpSize); +``` + +## Requirement: +For hardware requirement and software installation [Installation](https://github.com/ROCm-Developer-Tools/HIP/blob/master/INSTALL.md) + +## prerequiste knowledge: + +Programmers familiar with CUDA, OpenCL will be able to quickly learn and start coding with the HIP API. In case you are not, don't worry. You choose to start with the best one. We'll be explaining everything assuming you are completely new to gpgpu programming. + +## Simple Matrix Transpose + +We will be using the Simple Matrix Transpose application from the previous tutorial and modify it to learn how to use shared memory. + +## __shfl ops in 2D + +In the same sourcecode, we used for MatrixTranspose. We'll add the following: +``` + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + out[x*width + y] = __shfl(val,y*width + x); +``` + +With the help of this application, we can say that kernel code can be converted into multi-dimensional threads with ease. + +## How to build and run: +Use the make command and execute it using ./exe +Use hipcc to build the application, which is using hcc on AMD and nvcc on nvidia. + +## requirement for nvidia +please make sure you have a 3.0 or higher compute capable device in order to use warp shfl operations and add `-gencode arch=compute=30, code=sm_30` nvcc flag in the Makefile while using this application. + +## More Info: +- [HIP FAQ](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_faq.md) +- [HIP Kernel Language](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_kernel_language.md) +- [HIP Runtime API (Doxygen)](http://rocm-developer-tools.github.io/HIP) +- [HIP Porting Guide](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_porting_guide.md) +- [HIP Terminology](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_terms.md) (including Rosetta Stone of GPU computing terms across CUDA/HIP/HC/AMP/OpenL) +- [HIPIFY](https://github.com/ROCm-Developer-Tools/HIPIFY/blob/master/README.md) +- [Developer/CONTRIBUTING Info](https://github.com/ROCm-Developer-Tools/HIP/blob/master/CONTRIBUTING.md) +- [Release Notes](https://github.com/ROCm-Developer-Tools/HIP/blob/master/RELEASE.md) diff --git a/HIP/shfl/CMakeLists.txt b/HIP/shfl/CMakeLists.txt new file mode 100644 index 0000000..394d585 --- /dev/null +++ b/HIP/shfl/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +project(shfl) + +cmake_minimum_required(VERSION 3.10) + +if (NOT DEFINED ROCM_PATH ) + set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) +endif () + +# Search for rocm in common locations +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) + +# Find hip +find_package(hip) + +# Set compiler and linker +set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_BUILD_TYPE Release) + +# Create the excutable +add_executable(shfl shfl.cpp) + +# Link with HIP +target_link_libraries(shfl hip::host) diff --git a/HIP/shfl/Makefile b/HIP/shfl/Makefile new file mode 100644 index 0000000..76559c1 --- /dev/null +++ b/HIP/shfl/Makefile @@ -0,0 +1,60 @@ +# Copyright (c) 2016 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ROCM_PATH?= $(wildcard /opt/rocm/) +HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) +ifeq (,$(HIP_PATH)) + HIP_PATH=../../.. +endif + +ifeq (gfx701, $(findstring gfx701,$(HCC_AMDGPU_TARGET))) + $(error gfx701 is not a supported device for this sample) +endif + +HIPCC=$(HIP_PATH)/bin/hipcc + +TARGET=hcc + +SOURCES = shfl.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +EXECUTABLE=./shfl + +.PHONY: test + + +all: $(EXECUTABLE) test + +CXXFLAGS =-g +CXX=$(HIPCC) + + +$(EXECUTABLE): $(OBJECTS) + $(HIPCC) $(OBJECTS) -o $@ + + +test: $(EXECUTABLE) + $(EXECUTABLE) + + +clean: + rm -f $(EXECUTABLE) + rm -f $(OBJECTS) + rm -f $(HIP_PATH)/src/*.o diff --git a/HIP/shfl/Readme.md b/HIP/shfl/Readme.md new file mode 100644 index 0000000..ac5dff9 --- /dev/null +++ b/HIP/shfl/Readme.md @@ -0,0 +1,53 @@ +## Warp shfl operations ### + +In this tutorial, we'll explain how to use the warp shfl operations to improve the performance. + +## Introduction: + +Let's talk about Warp first. The kernel code is executed in groups of fixed number of threads known as Warp. For nvidia WarpSize is 32 while for AMD, 32 for Polaris architecture and 64 for rest. Threads in a warp are referred to as lanes and are numbered from 0 to warpSize -1. With the help of shfl ops, we can directly exchange values of variable between threads without using any memory ops within a warp. There are four types of shfl ops: +``` + int __shfl (int var, int srcLane, int width=warpSize); + float __shfl (float var, int srcLane, int width=warpSize); + int __shfl_up (int var, unsigned int delta, int width=warpSize); + float __shfl_up (float var, unsigned int delta, int width=warpSize); + int __shfl_down (int var, unsigned int delta, int width=warpSize); + float __shfl_down (float var, unsigned int delta, int width=warpSize); + int __shfl_xor (int var, int laneMask, int width=warpSize) + float __shfl_xor (float var, int laneMask, int width=warpSize); +``` + +## Requirement: +For hardware requirement and software installation [Installation](https://github.com/ROCm-Developer-Tools/HIP/blob/master/INSTALL.md) + +## prerequiste knowledge: + +Programmers familiar with CUDA, OpenCL will be able to quickly learn and start coding with the HIP API. In case you are not, don't worry. You choose to start with the best one. We'll be explaining everything assuming you are completely new to gpgpu programming. + +## Simple Matrix Transpose + +We will be using the Simple Matrix Transpose application from the previous tutorial and modify it to learn how to use shared memory. + +## __shfl ops + +In this tutorial, we'll use `__shfl()` ops. In the same sourcecode, we used for MatrixTranspose. We'll add the following: + +` out[i*width + j] = __shfl(val,j*width + i);` + +Be careful while using shfl operations, since all exchanges are possible between the threads of corresponding warp only. + +## How to build and run: +Use the make command and execute it using ./exe +Use hipcc to build the application, which is using hcc on AMD and nvcc on nvidia. + +## requirement for nvidia +please make sure you have a 3.0 or higher compute capable device in order to use warp shfl operations and add `-gencode arch=compute=30, code=sm_30` nvcc flag in the Makefile while using this application. + +## More Info: +- [HIP FAQ](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_faq.md) +- [HIP Kernel Language](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_kernel_language.md) +- [HIP Runtime API (Doxygen)](http://rocm-developer-tools.github.io/HIP) +- [HIP Porting Guide](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_porting_guide.md) +- [HIP Terminology](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_terms.md) (including Rosetta Stone of GPU computing terms across CUDA/HIP/HC/AMP/OpenL) +- [HIPIFY](https://github.com/ROCm-Developer-Tools/HIPIFY/blob/master/README.md) +- [Developer/CONTRIBUTING Info](https://github.com/ROCm-Developer-Tools/HIP/blob/master/CONTRIBUTING.md) +- [Release Notes](https://github.com/ROCm-Developer-Tools/HIP/blob/master/RELEASE.md) diff --git a/HIP/shfl/shfl.cpp b/HIP/shfl/shfl.cpp new file mode 100644 index 0000000..7902fd1 --- /dev/null +++ b/HIP/shfl/shfl.cpp @@ -0,0 +1,124 @@ +/* +Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <iostream> + +// hip header file +#include "hip/hip_runtime.h" + + +#define WIDTH 4 + +#define NUM (WIDTH * WIDTH) + +#define THREADS_PER_BLOCK_X 4 +#define THREADS_PER_BLOCK_Y 4 +#define THREADS_PER_BLOCK_Z 1 + +// Device (Kernel) function, it must be void +__global__ void matrixTranspose(float* out, float* in, const int width) { + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + + float val = in[x]; + + for (int i = 0; i < width; i++) { + for (int j = 0; j < width; j++) out[i * width + j] = __shfl(val, j * width + i); + } +} + +// CPU implementation of matrix transpose +void matrixTransposeCPUReference(float* output, float* input, const unsigned int width) { + for (unsigned int j = 0; j < width; j++) { + for (unsigned int i = 0; i < width; i++) { + output[i * width + j] = input[j * width + i]; + } + } +} + +int main() { + float* Matrix; + float* TransposeMatrix; + float* cpuTransposeMatrix; + + float* gpuMatrix; + float* gpuTransposeMatrix; + + hipDeviceProp_t devProp; + hipGetDeviceProperties(&devProp, 0); + + std::cout << "Device name " << devProp.name << std::endl; + + int i; + int errors; + + Matrix = (float*)malloc(NUM * sizeof(float)); + TransposeMatrix = (float*)malloc(NUM * sizeof(float)); + cpuTransposeMatrix = (float*)malloc(NUM * sizeof(float)); + + // initialize the input data + for (i = 0; i < NUM; i++) { + Matrix[i] = (float)i * 10.0f; + } + + // allocate the memory on the device side + hipMalloc((void**)&gpuMatrix, NUM * sizeof(float)); + hipMalloc((void**)&gpuTransposeMatrix, NUM * sizeof(float)); + + // Memory transfer from host to device + hipMemcpy(gpuMatrix, Matrix, NUM * sizeof(float), hipMemcpyHostToDevice); + + // Lauching kernel from host + hipLaunchKernelGGL(matrixTranspose, dim3(1), dim3(THREADS_PER_BLOCK_X * THREADS_PER_BLOCK_Y), 0, 0, + gpuTransposeMatrix, gpuMatrix, WIDTH); + + // Memory transfer from device to host + hipMemcpy(TransposeMatrix, gpuTransposeMatrix, NUM * sizeof(float), hipMemcpyDeviceToHost); + + // CPU MatrixTranspose computation + matrixTransposeCPUReference(cpuTransposeMatrix, Matrix, WIDTH); + + // verify the results + errors = 0; + double eps = 1.0E-6; + for (i = 0; i < NUM; i++) { + if (std::abs(TransposeMatrix[i] - cpuTransposeMatrix[i]) > eps) { + printf("%d cpu: %f gpu %f\n", i, cpuTransposeMatrix[i], TransposeMatrix[i]); + errors++; + } + } + if (errors != 0) { + printf("FAILED: %d errors\n", errors); + } else { + printf("PASSED!\n"); + } + + // free the resources on device side + hipFree(gpuMatrix); + hipFree(gpuTransposeMatrix); + + // free the resources on host side + free(Matrix); + free(TransposeMatrix); + free(cpuTransposeMatrix); + + return errors; +} -- GitLab From e4badac17b8aad7f6edd7aed3906d42d6bcdd2f8 Mon Sep 17 00:00:00 2001 From: Umesh Seth <umeshseth@login2.crusher.olcf.ornl.gov> Date: Wed, 2 Nov 2022 05:11:12 -0400 Subject: [PATCH 9/9] add unroll and peer2peer examples --- HIP/peer2peer/CMakeLists.txt | 43 +++++++ HIP/peer2peer/Makefile | 57 +++++++++ HIP/peer2peer/peer2peer.cpp | 226 +++++++++++++++++++++++++++++++++++ HIP/unroll/CMakeLists.txt | 43 +++++++ HIP/unroll/Makefile | 60 ++++++++++ HIP/unroll/Readme.md | 48 ++++++++ HIP/unroll/unroll.cpp | 122 +++++++++++++++++++ 7 files changed, 599 insertions(+) create mode 100644 HIP/peer2peer/CMakeLists.txt create mode 100644 HIP/peer2peer/Makefile create mode 100644 HIP/peer2peer/peer2peer.cpp create mode 100644 HIP/unroll/CMakeLists.txt create mode 100644 HIP/unroll/Makefile create mode 100644 HIP/unroll/Readme.md create mode 100644 HIP/unroll/unroll.cpp diff --git a/HIP/peer2peer/CMakeLists.txt b/HIP/peer2peer/CMakeLists.txt new file mode 100644 index 0000000..ad34ee4 --- /dev/null +++ b/HIP/peer2peer/CMakeLists.txt @@ -0,0 +1,43 @@ +# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +project(peer2peer) + +cmake_minimum_required(VERSION 3.10) + +if (NOT DEFINED ROCM_PATH ) + set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) +endif () + +# Search for rocm in common locations +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) + +# Find hip +find_package(hip) + +# Set compiler and linker +set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) + +# Create the excutable +add_executable(peer2peer peer2peer.cpp) + +# Link with HIP +target_link_libraries(peer2peer hip::host) diff --git a/HIP/peer2peer/Makefile b/HIP/peer2peer/Makefile new file mode 100644 index 0000000..555e92e --- /dev/null +++ b/HIP/peer2peer/Makefile @@ -0,0 +1,57 @@ +# Copyright (c) 2016 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ROCM_PATH?= $(wildcard /opt/rocm/) +HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) +ifeq (,$(HIP_PATH)) + HIP_PATH=../../.. +endif + +HIPCC=$(HIP_PATH)/bin/hipcc + +TARGET=hcc + +SOURCES = peer2peer.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +EXECUTABLE=./peer2peer + +.PHONY: test + + +all: $(EXECUTABLE) test + +CXXFLAGS =-g +CXX=$(HIPCC) + + +$(EXECUTABLE): $(OBJECTS) + $(HIPCC) $(OBJECTS) -o $@ + + +test: $(EXECUTABLE) + $(EXECUTABLE) + + +clean: + rm -f $(EXECUTABLE) + rm -f $(OBJECTS) + rm -f $(HIP_PATH)/src/*.o + diff --git a/HIP/peer2peer/peer2peer.cpp b/HIP/peer2peer/peer2peer.cpp new file mode 100644 index 0000000..4ec6372 --- /dev/null +++ b/HIP/peer2peer/peer2peer.cpp @@ -0,0 +1,226 @@ +/* +Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANUMTY OF ANY KIND, EXPRESS OR +IMPLIED, INUMCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNUMESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANUMY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER INUM AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR INUM CONUMECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <iostream> +#include <hip/hip_runtime.h> +#include <assert.h> +#define WIDTH 32 + +#define NUM (WIDTH * WIDTH) + +#define THREADS_PER_BLOCK_X 4 +#define THREADS_PER_BLOCK_Y 4 +#define THREADS_PER_BLOCK_Z 1 + +using namespace std; + +#define KNRM "\x1B[0m" +#define KRED "\x1B[31m" + +#define failed(...) \ + printf("%serror: ", KRED); \ + printf(__VA_ARGS__); \ + printf("\n"); \ + printf("error: TEST FAILED\n%s", KNRM); \ + abort(); + +#define HIPCHECK(error) \ + { \ + hipError_t localError = error; \ + if ((localError != hipSuccess)&& (localError != hipErrorPeerAccessAlreadyEnabled)&& \ + (localError != hipErrorPeerAccessNotEnabled )) { \ + printf("%serror: '%s'(%d) from %s at %s:%d%s\n", KRED, hipGetErrorString(localError), \ + localError, #error, __FILE__, __LINE__, KNRM); \ + failed("API returned error code."); \ + } \ + } + +void checkPeer2PeerSupport() { + int gpuCount; + int canAccessPeer; + + HIPCHECK(hipGetDeviceCount(&gpuCount)); + + for (int currentGpu = 0; currentGpu < gpuCount; currentGpu++) { + HIPCHECK(hipSetDevice(currentGpu)); + + for (int peerGpu = 0; peerGpu < currentGpu; peerGpu++) { + if (currentGpu != peerGpu) { + HIPCHECK(hipDeviceCanAccessPeer(&canAccessPeer, currentGpu, peerGpu)); + printf("currentGpu#%d canAccessPeer: peerGpu#%d=%d\n", currentGpu, peerGpu, + canAccessPeer); + } + + HIPCHECK(hipSetDevice(peerGpu)); + HIPCHECK(hipDeviceReset()); + } + HIPCHECK(hipSetDevice(currentGpu)); + HIPCHECK(hipDeviceReset()); + } +} + +void enablePeer2Peer(int currentGpu, int peerGpu) { + int canAccessPeer; + + // Must be on a multi-gpu system: + assert(currentGpu != peerGpu); + + HIPCHECK(hipSetDevice(currentGpu)); + hipDeviceCanAccessPeer(&canAccessPeer, currentGpu, peerGpu); + + if (canAccessPeer == 1) { + HIPCHECK(hipDeviceEnablePeerAccess(peerGpu, 0)); + } else + printf("peer2peer transfer not possible between the selected gpu devices"); +} + +void disablePeer2Peer(int currentGpu, int peerGpu) { + int canAccessPeer; + + // Must be on a multi-gpu system: + assert(currentGpu != peerGpu); + + HIPCHECK(hipSetDevice(currentGpu)); + hipDeviceCanAccessPeer(&canAccessPeer, currentGpu, peerGpu); + + if (canAccessPeer == 1) { + HIPCHECK(hipDeviceDisablePeerAccess(peerGpu)); + } else + printf("peer2peer disable not required"); +} + + +__global__ void matrixTranspose_static_shared(float* out, float* in, + const int width) { + __shared__ float sharedMem[WIDTH * WIDTH]; + + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + + sharedMem[y * width + x] = in[x * width + y]; + + __syncthreads(); + + out[y * width + x] = sharedMem[y * width + x]; +} + +__global__ void matrixTranspose_dynamic_shared(float* out, float* in, + const int width) { + extern __shared__ float sharedMem[]; + + int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; + int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y; + + sharedMem[y * width + x] = in[x * width + y]; + + __syncthreads(); + + out[y * width + x] = sharedMem[y * width + x]; +} + +int main() { + checkPeer2PeerSupport(); + + int gpuCount; + int currentGpu, peerGpu; + + HIPCHECK(hipGetDeviceCount(&gpuCount)); + + if (gpuCount < 2) { + printf("Peer2Peer application requires atleast 2 gpu devices"); + return 0; + } + + currentGpu = 0; + peerGpu = (currentGpu + 1); + + printf("currentGpu=%d peerGpu=%d (Total no. of gpu = %d)\n", currentGpu, peerGpu, gpuCount); + + float *data[2], *TransposeMatrix[2], *gpuTransposeMatrix[2], *randArray; + + int width = WIDTH; + + randArray = (float*)malloc(NUM * sizeof(float)); + + for (int i = 0; i < NUM; i++) { + randArray[i] = (float)i * 1.0f; + } + + enablePeer2Peer(currentGpu, peerGpu); + + HIPCHECK(hipSetDevice(currentGpu)); + TransposeMatrix[0] = (float*)malloc(NUM * sizeof(float)); + hipMalloc((void**)&gpuTransposeMatrix[0], NUM * sizeof(float)); + hipMalloc((void**)&data[0], NUM * sizeof(float)); + hipMemcpy(data[0], randArray, NUM * sizeof(float), hipMemcpyHostToDevice); + + hipLaunchKernelGGL(matrixTranspose_static_shared, + dim3(WIDTH / THREADS_PER_BLOCK_X, WIDTH / THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), 0, 0, gpuTransposeMatrix[0], + data[0], width); + HIPCHECK(hipDeviceSynchronize()); + + HIPCHECK(hipSetDevice(peerGpu)); + TransposeMatrix[1] = (float*)malloc(NUM * sizeof(float)); + hipMalloc((void**)&gpuTransposeMatrix[1], NUM * sizeof(float)); + hipMalloc((void**)&data[1], NUM * sizeof(float)); + hipMemcpy(data[1], gpuTransposeMatrix[0], NUM * sizeof(float), hipMemcpyDeviceToDevice); + + hipLaunchKernelGGL(matrixTranspose_dynamic_shared, + dim3(WIDTH / THREADS_PER_BLOCK_X, WIDTH / THREADS_PER_BLOCK_Y), + dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y), sizeof(float) * WIDTH * WIDTH, + 0, gpuTransposeMatrix[1], data[1], width); + + hipMemcpy(TransposeMatrix[1], gpuTransposeMatrix[1], NUM * sizeof(float), + hipMemcpyDeviceToHost); + + hipDeviceSynchronize(); + + disablePeer2Peer(currentGpu, peerGpu); + + // verify the results + int errors = 0; + double eps = 1.0E-6; + for (int i = 0; i < NUM; i++) { + if (std::abs(randArray[i] - TransposeMatrix[1][i]) > eps) { + printf("%d cpu: %f gpu peered data %f\n", i, randArray[i], TransposeMatrix[1][i]); + errors++; + } + } + if (errors != 0) { + printf("FAILED: %d errors\n", errors); + } else { + printf("Peer2Peer PASSED!\n"); + } + + free(randArray); + for (int i = 0; i < 2; i++) { + hipFree(data[i]); + hipFree(gpuTransposeMatrix[i]); + free(TransposeMatrix[i]); + } + + HIPCHECK(hipSetDevice(peerGpu)); + HIPCHECK(hipDeviceReset()); + + HIPCHECK(hipSetDevice(currentGpu)); + HIPCHECK(hipDeviceReset()); + + return 0; +} diff --git a/HIP/unroll/CMakeLists.txt b/HIP/unroll/CMakeLists.txt new file mode 100644 index 0000000..258138f --- /dev/null +++ b/HIP/unroll/CMakeLists.txt @@ -0,0 +1,43 @@ +# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +project(unroll) + +cmake_minimum_required(VERSION 3.10) + +if (NOT DEFINED ROCM_PATH ) + set ( ROCM_PATH "/opt/rocm" CACHE STRING "Default ROCM installation directory." ) +endif () + +# Search for rocm in common locations +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) + +# Find hip +find_package(hip) + +# Set compiler and linker +set(CMAKE_CXX_COMPILER ${HIP_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_LINKER ${HIP_HIPCC_EXECUTABLE}) + +# Create the excutable +add_executable(unroll unroll.cpp) + +# Link with HIP +target_link_libraries(unroll hip::host) diff --git a/HIP/unroll/Makefile b/HIP/unroll/Makefile new file mode 100644 index 0000000..d1e3321 --- /dev/null +++ b/HIP/unroll/Makefile @@ -0,0 +1,60 @@ +# Copyright (c) 2017 - 2021 Advanced Micro Devices, Inc. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ROCM_PATH?= $(wildcard /opt/rocm/) +HIP_PATH?= $(wildcard $(ROCM_PATH)/hip) +ifeq (,$(HIP_PATH)) + HIP_PATH=../../.. +endif + +ifeq (gfx701, $(findstring gfx701,$(HCC_AMDGPU_TARGET))) + $(error gfx701 is not a supported device for this sample) +endif + +HIPCC=$(HIP_PATH)/bin/hipcc + +TARGET=hcc + +SOURCES = unroll.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +EXECUTABLE=./unroll + +.PHONY: test + + +all: $(EXECUTABLE) test + +CXXFLAGS =-g +CXX=$(HIPCC) + + +$(EXECUTABLE): $(OBJECTS) + $(HIPCC) $(OBJECTS) -o $@ + + +test: $(EXECUTABLE) + $(EXECUTABLE) + + +clean: + rm -f $(EXECUTABLE) + rm -f $(OBJECTS) + rm -f $(HIP_PATH)/src/*.o diff --git a/HIP/unroll/Readme.md b/HIP/unroll/Readme.md new file mode 100644 index 0000000..6fad55e --- /dev/null +++ b/HIP/unroll/Readme.md @@ -0,0 +1,48 @@ +## Using Pragma unroll ### + +In this tutorial, we'll explain how to use #pragma unroll to improve the performance. + +## Introduction: + +Loop unrolling optimization hints can be specified with #pragma unroll and #pragma nounroll. The pragma is placed immediately before a for loop. +Specifying #pragma unroll without a parameter directs the loop unroller to attempt to fully unroll the loop if the trip count is known at compile time and attempt to partially unroll the loop if the trip count is not known at compile time. + +## Requirement: +For hardware requirement and software installation [Installation](https://github.com/ROCm-Developer-Tools/HIP/blob/master/INSTALL.md) + +## prerequiste knowledge: + +Programmers familiar with CUDA, OpenCL will be able to quickly learn and start coding with the HIP API. In case you are not, don't worry. You choose to start with the best one. We'll be explaining everything assuming you are completely new to gpgpu programming. + +## Simple Matrix Transpose + +For this tutorial we will be using an example which sums up the row of a 2D matrix and writes it in a 1D array. + +In this tutorial, we'll use `#pragma unroll`. In the same sourcecode, we used for gpuMatrixRowSum. We'll add it just before the for loop as following: + +``` +#pragma unroll +for (int i = 0; i < width; i++) { + output[index] += input[index * width + i] +} +``` + +Specifying the optional parameter, #pragma unroll value, directs the unroller to unroll the loop value times. Be careful while using it. +Specifying #pragma nounroll indicates that the loop should not be unroll. #pragma unroll 1 will show the same behaviour. + +## How to build and run: +Use the make command and execute it using ./exe +Use hipcc to build the application, which is using hcc on AMD and nvcc on nvidia. + +## requirement for nvidia +please make sure you have a 3.0 or higher compute capable device in order to use warp shfl operations and add `-gencode arch=compute=30, code=sm_30` nvcc flag in the Makefile while using this application. + +## More Info: +- [HIP FAQ](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_faq.md) +- [HIP Kernel Language](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_kernel_language.md) +- [HIP Runtime API (Doxygen)](http://rocm-developer-tools.github.io/HIP) +- [HIP Porting Guide](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_porting_guide.md) +- [HIP Terminology](https://github.com/ROCm-Developer-Tools/HIP/blob/master/docs/markdown/hip_terms.md) (including Rosetta Stone of GPU computing terms across CUDA/HIP/HC/AMP/OpenL) +- [HIPIFY](https://github.com/ROCm-Developer-Tools/HIPIFY/blob/master/README.md) +- [Developer/CONTRIBUTING Info](https://github.com/ROCm-Developer-Tools/HIP/blob/master/CONTRIBUTING.md) +- [Release Notes](https://github.com/ROCm-Developer-Tools/HIP/blob/master/RELEASE.md) diff --git a/HIP/unroll/unroll.cpp b/HIP/unroll/unroll.cpp new file mode 100644 index 0000000..8d65984 --- /dev/null +++ b/HIP/unroll/unroll.cpp @@ -0,0 +1,122 @@ +/* +Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <iostream> + +// hip header file +#include "hip/hip_runtime.h" + +#define LENGTH 4 + +#define SIZE (LENGTH * LENGTH) + +#define THREADS_PER_BLOCK 1 +#define BLOCKS_PER_GRID LENGTH + +// CPU function - basically scan each row and save the output in array +void matrixRowSum(int* input, int* output, int width) { + for (int i = 0; i < width; i++) { + for (int j = 0; j < width; j++) { + output[i] += input[i * width + j]; + } + } +} + +// Device (kernel) function +__global__ void gpuMatrixRowSum(int* input, int* output, int width) { + int index = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x; +#pragma unroll + for (int i = 0; i < width; i++) { + output[index] += input[index * width + i]; + } +} + +int main() { + int* Matrix; + int* sumMatrix; + int* cpuSumMatrix; + + int* gpuMatrix; + int* gpuSumMatrix; + + hipDeviceProp_t devProp; + hipGetDeviceProperties(&devProp, 0); + + std::cout << "Device name " << devProp.name << std::endl; + + Matrix = (int*)malloc(sizeof(int) * SIZE); + sumMatrix = (int*)malloc(sizeof(int) * LENGTH); + cpuSumMatrix = (int*)malloc(sizeof(int) * LENGTH); + + for (int i = 0; i < SIZE; i++) { + Matrix[i] = i * 2; + } + + for (int i = 0; i < LENGTH; i++) { + cpuSumMatrix[i] = 0; + } + + // Allocated Device Memory + hipMalloc((void**)&gpuMatrix, SIZE * sizeof(int)); + hipMalloc((void**)&gpuSumMatrix, LENGTH * sizeof(int)); + + // Memory Copy to Device + hipMemcpy(gpuMatrix, Matrix, SIZE * sizeof(int), hipMemcpyHostToDevice); + hipMemcpy(gpuSumMatrix, cpuSumMatrix, LENGTH * sizeof(float), hipMemcpyHostToDevice); + + // Launch device kernels + hipLaunchKernelGGL(gpuMatrixRowSum, dim3(BLOCKS_PER_GRID), dim3(THREADS_PER_BLOCK), 0, 0, + gpuMatrix, gpuSumMatrix, LENGTH); + + // Memory copy back to device + hipMemcpy(sumMatrix, gpuSumMatrix, LENGTH * sizeof(int), hipMemcpyDeviceToHost); + + // Cpu implementation + matrixRowSum(Matrix, cpuSumMatrix, LENGTH); + + + // verify the results + int errors = 0; + for (int i = 0; i < LENGTH; i++) { + if (sumMatrix[i] != cpuSumMatrix[i]) { + printf("%d - cpu: %d gpu: %d\n", i, sumMatrix[i], cpuSumMatrix[i]); + errors++; + } + } + + if (errors == 0) { + printf("PASSED\n"); + } else { + printf("FAILED with %d errors\n", errors); + } + + // GPU Free + hipFree(gpuMatrix); + hipFree(gpuSumMatrix); + + // CPU Free + free(Matrix); + free(sumMatrix); + free(cpuSumMatrix); + + return errors; +} -- GitLab