diff --git a/test/MatrixTranspose_test/Makefile b/test/MatrixTranspose_test/Makefile index 06aec81b84..5a780799c6 100644 --- a/test/MatrixTranspose_test/Makefile +++ b/test/MatrixTranspose_test/Makefile @@ -2,31 +2,38 @@ ROOT_PATH = ../.. LIB_PATH = $(ROOT_PATH)/build ROC_LIBS = -L$(LIB_PATH) -lroctracer64 -lroctx64 -EXECUTABLE = ./MatrixTranspose -SOURCES = MatrixTranspose.cpp -OBJECTS = $(SOURCES:.cpp=.o) - ITERATIONS ?= 100 HCC_HOME ?= /opt/rocm/hcc HIP_PATH ?= /opt/rocm/hip -HIPCC = $(HIP_PATH)/bin/hipcc +HIPCC=$(HIP_PATH)/bin/hipcc CXX = $(HIPCC) CXXFLAGS = -g -I$(ROOT_PATH) -I$(ROOT_PATH)/inc -DLOCAL_BUILD=1 -DITERATIONS=$(ITERATIONS) +TARGET=hcc + +SOURCES = MatrixTranspose.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +EXECUTABLE=./MatrixTranspose + export LD_LIBRARY_PATH=$(LIB_PATH) -all: clean $(EXECUTABLE) +.PHONY: test + + +all: $(EXECUTABLE) test + $(EXECUTABLE): $(OBJECTS) - $(HIPCC) $(OBJECTS) -o $@ $(HCC_LIBS) $(ROC_LIBS) + $(HIPCC) $(OBJECTS) -o $@ $(ROC_LIBS) test: $(EXECUTABLE) - LD_PRELOAD=$(HCC_HOME)/lib/libmcwamp_hsa.so $(EXECUTABLE) + $(EXECUTABLE) clean: rm -f $(EXECUTABLE) rm -f $(OBJECTS) + rm -f $(HIP_PATH)/src/*.o -.PHONY: all test clean diff --git a/test/MatrixTranspose_test/MatrixTranspose.cpp b/test/MatrixTranspose_test/MatrixTranspose.cpp index 3a756125b2..7ca24d0f0b 100644 --- a/test/MatrixTranspose_test/MatrixTranspose.cpp +++ b/test/MatrixTranspose_test/MatrixTranspose.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved. +Copyright (c) 2015-present 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 @@ -44,8 +44,7 @@ THE SOFTWARE. #define THREADS_PER_BLOCK_Z 1 // Device (Kernel) function, it must be void -// hipLaunchParm provides the execution configuration -__global__ void matrixTranspose(hipLaunchParm lp, float* out, float* in, const int width) { +__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; @@ -85,88 +84,88 @@ int main() { init_tracing(); while (iterations-- > 0) { - start_tracing(); + start_tracing(); - 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; + 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)); + + // correlation reagion32 + roctracer_activity_push_external_correlation_id(31); + // correlation reagion32 + roctracer_activity_push_external_correlation_id(32); + + // Memory transfer from host to device + hipMemcpy(gpuMatrix, Matrix, NUM * sizeof(float), hipMemcpyHostToDevice); + + // correlation reagion33 + roctracer_activity_push_external_correlation_id(33); + + roctxMark("before hipLaunchKernel"); + roctxRangePush("hipLaunchKernel"); + + // 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); + + roctxMark("after hipLaunchKernel"); + + // correlation reagion end + roctracer_activity_pop_external_correlation_id(NULL); + + // Memory transfer from device to host + roctxRangePush("hipMemcpy"); + + hipMemcpy(TransposeMatrix, gpuTransposeMatrix, NUM * sizeof(float), hipMemcpyDeviceToHost); + + roctxRangePop(); // for "hipMemcpy" + roctxRangePop(); // for "hipLaunchKernel" + + // correlation reagion end + roctracer_activity_pop_external_correlation_id(); + + // 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++; } - - // allocate the memory on the device side - hipMalloc((void**)&gpuMatrix, NUM * sizeof(float)); - hipMalloc((void**)&gpuTransposeMatrix, NUM * sizeof(float)); - - // correlation reagion32 - roctracer_activity_push_external_correlation_id(31); - // correlation reagion32 - roctracer_activity_push_external_correlation_id(32); + } + if (errors != 0) { + printf("FAILED: %d errors\n", errors); + } else { + printf("PASSED!\n"); + } - // Memory transfer from host to device - hipMemcpy(gpuMatrix, Matrix, NUM * sizeof(float), hipMemcpyHostToDevice); + // free the resources on device side + hipFree(gpuMatrix); + hipFree(gpuTransposeMatrix); - // correlation reagion33 - roctracer_activity_push_external_correlation_id(33); + // correlation reagion end + roctracer_activity_pop_external_correlation_id(); + // correlation reagion end + roctracer_activity_pop_external_correlation_id(); - roctxMark("before hipLaunchKernel"); - roctxRangePush("hipLaunchKernel"); + // free the resources on host side + free(Matrix); + free(TransposeMatrix); + free(cpuTransposeMatrix); - // Lauching kernel from host - hipLaunchKernel(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); - - roctxMark("after hipLaunchKernel"); - - // correlation reagion end - roctracer_activity_pop_external_correlation_id(NULL); - - // Memory transfer from device to host - roctxRangePush("hipMemcpy"); - - hipMemcpy(TransposeMatrix, gpuTransposeMatrix, NUM * sizeof(float), hipMemcpyDeviceToHost); - - roctxRangePop(); // for "hipMemcpy" - roctxRangePop(); // for "hipLaunchKernel" - - // correlation reagion end - roctracer_activity_pop_external_correlation_id(); - - // 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); - - // correlation reagion end - roctracer_activity_pop_external_correlation_id(); - // correlation reagion end - roctracer_activity_pop_external_correlation_id(); - - // free the resources on host side - free(Matrix); - free(TransposeMatrix); - free(cpuTransposeMatrix); - - stop_tracing(); + stop_tracing(); } return errors; diff --git a/test/MatrixTranspose_test/Readme.md b/test/MatrixTranspose_test/Readme.md index ab5dbdc958..8f19613f87 100644 --- a/test/MatrixTranspose_test/Readme.md +++ b/test/MatrixTranspose_test/Readme.md @@ -7,31 +7,32 @@ This tutorial shows how to get write simple HIP application. We will write the s 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/INSTALL.md) +For hardware requirement and software installation [Installation](https://github.com/ROCm-Developer-Tools/HIP/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 +## 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). +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(hipLaunchParm lp, ` -` 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__ 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: @@ -41,13 +42,11 @@ other function-type qualifiers are: `__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*. +`__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, and the first parameter to a HIP `__global__` function must have the type `hipLaunchParm`, which is for execution configuration. 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. +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. -After `hipLaunchParm`, Kernel arguments follows next(i.e., `float *out, float *in, const int width, const int height`). - -The kernel function begins with +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. @@ -63,18 +62,20 @@ We allocated memory to the Matrix on host side by using malloc and initiallized 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. -` hipLaunchKernel(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); ` +``` + 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 `"hipLaunchKernel"` function -- The first five parameters to hipLaunchKernel are the following: +- 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)". + - **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".