Merge 'master' into 'amd-master'

Change-Id: Ibb1dbe78aa52c8aeb77851ee1471e1edaec4c654


[ROCm/hip commit: cbe6b65e2c]
Этот коммит содержится в:
Jenkins
2019-09-09 05:10:28 -04:00
родитель bc0c065835 cec523f647
Коммит 2f7a11093f
20 изменённых файлов: 1966 добавлений и 1107 удалений
+8
Просмотреть файл
@@ -55,6 +55,14 @@ add_to_config(_versionInfo HIP_VERSION_MAJOR)
add_to_config(_versionInfo HIP_VERSION_MINOR)
add_to_config(_versionInfo HIP_VERSION_PATCH)
if(CMAKE_CXX_COMPILER MATCHES ".*hcc")
set(HIP_COMPILER "hcc" CACHE STRING "HIP Compiler")
set(HIP_PLATFORM "hcc" CACHE STRING "HIP Platform")
get_filename_component(CXX_PATH ${CMAKE_CXX_COMPILER} DIRECTORY)
get_filename_component(CXX_PATH ${CXX_PATH} DIRECTORY)
set(HCC_HOME "${CXX_PATH}" CACHE PATH "Path to which HCC has been installed")
endif()
# overwrite HIP_VERSION_PATCH for packaging
if(DEFINED ENV{ROCM_BUILD_ID})
set(HIP_VERSION_PATCH ${HIP_VERSION_GITDATE}.${HIP_VERSION_GITCOUNT}-$ENV{ROCM_BUILD_ID}-${HIP_VERSION_GITHASH})
Разница между файлами не показана из-за своего большого размера Загрузить разницу
+15 -16
Просмотреть файл
@@ -11,6 +11,7 @@ and provides practical suggestions on how to port CUDA code and work through com
* [General Tips](#general-tips)
* [Scanning existing CUDA code to scope the porting effort](#scanning-existing-cuda-code-to-scope-the-porting-effort)
* [Converting a project "in-place"](#converting-a-project-in-place)
* [CUDA to HIP Math Library Equivalents](#library-equivalents)
- [Distinguishing Compiler Modes](#distinguishing-compiler-modes)
* [Identifying HIP Target Platform](#identifying-hip-target-platform)
* [Identifying the Compiler: hcc, hip-clang, or nvcc](#identifying-the-compiler-hcc-hip-clang-or-nvcc)
@@ -46,7 +47,6 @@ and provides practical suggestions on how to port CUDA code and work through com
+ [/usr/include/c++/v1/memory:5172:15: error: call to implicitly deleted default constructor of 'std::__1::bad_weak_ptr' throw bad_weak_ptr();](#usrincludecv1memory517215-error-call-to-implicitly-deleted-default-constructor-of-std__1bad_weak_ptr-throw-bad_weak_ptr)
* [HIP Environment Variables](#hip-environment-variables)
* [Editor Highlighting](#editor-highlighting)
* [CUDA to HIP Math Library Equivalents](#library-equivalents)
<!-- tocstop -->
@@ -124,7 +124,21 @@ directory names.
> hipconvertinplace.sh MY_SRC_DIR
```
### Library Equivalents
| CUDA Library | ROCm Library | Comment |
|------- | --------- | ----- |
| cuBLAS | rocBLAS | Basic Linear Algebra Subroutines
| cuFFT | rocFFT | Fast Fourier Transfer Library
| cuSPARSE | rocSPARSE | Sparse BLAS + SPMV
| cuSolver | rocSolver | Lapack library
| AMG-X | rocALUTION | Sparse iterative solvers and preconditioners with Geometric and Algebraic MultiGrid
| Thrust | hipThrust | C++ parallel algorithms library
| CUB | rocPRIM | Low Level Optimized Parallel Primitives
| cuDNN | MIOpen | Deep learning Solver Library
| cuRAND | rocRAND | Random Number Generator Library
| EIGEN | EIGEN – HIP port | C++ template library for linear algebra: matrices, vectors, numerical solvers,
| NCCL | RCCL | Communications Primitives Library based on the MPI equivalents
@@ -559,18 +573,3 @@ HIP_VISIBLE_DEVICES = 0 : Only devices whose index is present in the
See the utils/vim or utils/gedit directories to add handy highlighting to hip files.
### Library Equivalents
| CUDA Library | ROCm Library | Comment |
|------- | --------- | ----- |
| cuBLAS | rocBLAS | Basic Linear Algebra Subroutines
| cuFFT | rocFFT | Fast Fourier Transfer Library
| cuSPARSE | rocSPARSE | Sparse BLAS + SPMV
| cuSolver | rocSolver | Lapack library
| AMG-X | rocALUTION | Sparse iterative solvers and preconditioners with Geometric and Algebraic MultiGrid
| Thrust | hipThrust | C++ parallel algorithms library
| CUB | rocPRIM | Low Level Optimized Parallel Primitives
| cuDNN | MIOpen | Deep learning Solver Library
| cuRAND | rocRAND | Random Number Generator Library
| EIGEN | EIGEN – HIP port | C++ template library for linear algebra: matrices, vectors, numerical solvers,
| NCCL | RCCL | Communications Primitives Library based on the MPI equivalents
+1 -8
Просмотреть файл
@@ -1,14 +1,7 @@
if (CUDA_VERSION VERSION_GREATER "9.2")
cmake_minimum_required(VERSION 3.12.3)
else()
if (CUDA_VERSION VERSION_LESS "9.0")
cmake_minimum_required(VERSION 3.5.0)
else()
cmake_minimum_required(VERSION 3.6.0)
endif()
if (MSVC AND MSVC_VERSION VERSION_GREATER "1900")
cmake_minimum_required(VERSION 3.7.2)
endif()
cmake_minimum_required(VERSION 3.7.2)
endif()
project(hipify-clang)
+72 -68
Просмотреть файл
@@ -143,9 +143,9 @@ To run it:
* Path to cuDNN should be specified by the `CUDA_DNN_ROOT_DIR` option:
- Linux: `-DCUDA_DNN_ROOT_DIR=/srv/CUDNN/cudnn-10.0-v7.6.2.24`
- Linux: `-DCUDA_DNN_ROOT_DIR=/srv/CUDNN/cudnn-10.0-v7.6.3.30`
- Windows: `-DCUDA_DNN_ROOT_DIR=f:/CUDNN/cudnn-9.0-windows10-x64-v7.6.2.24`
- Windows: `-DCUDA_DNN_ROOT_DIR=f:/CUDNN/cudnn-9.0-windows10-x64-v7.6.3.30`
5. Ensure [`python`](https://www.python.org/downloads) of minimum required version 2.7 is installed.
@@ -179,9 +179,9 @@ To run it:
On Linux the following configurations are tested:
Ubuntu 14: LLVM 5.0.0 - 6.0.1, CUDA 7.0 - 9.0, cudnn-5.0.5 - cudnn-7.6.2.24
Ubuntu 14: LLVM 5.0.0 - 6.0.1, CUDA 7.0 - 9.0, cudnn-5.0.5 - cudnn-7.6.3.30
Ubuntu 16-18: LLVM 8.0.0 - 8.0.1, CUDA 8.0 - 10.0, cudnn-5.1.10 - cudnn-7.6.2.24
Ubuntu 16-18: LLVM 8.0.0 - 8.0.1, CUDA 8.0 - 10.0, cudnn-5.1.10 - cudnn-7.6.3.30
Build system for the above configurations:
@@ -196,7 +196,7 @@ cmake
-DCMAKE_INSTALL_PREFIX=../dist \
-DCMAKE_PREFIX_PATH=/srv/git/LLVM/8.0.1/dist \
-DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-10.0 \
-DCUDA_DNN_ROOT_DIR=/srv/CUDNN/cudnn-10.0-v7.6.2.24 \
-DCUDA_DNN_ROOT_DIR=/srv/CUDNN/cudnn-10.0-v7.6.3.30 \
-DLLVM_EXTERNAL_LIT=/srv/git/LLVM/8.0.1/build/bin/llvm-lit \
..
```
@@ -248,67 +248,71 @@ Running HIPify regression tests
CUDA 10.0 - will be used for testing
LLVM 8.0.1 - will be used for testing
x86_64 - Platform architecture
Linux 5.2.0-rc1-kfd-compute-roc-master-int-hipclang-623 - Platform OS
Linux 5.2.0 - Platform OS
64 - hipify-clang binary bitness
64 - python 2.7.12 binary bitness
========================================
-- Testing: 54 tests, 12 threads --
PASS: hipify :: unit_tests/headers/headers_test_03.cu (1 of 54)
PASS: hipify :: unit_tests/headers/headers_test_02.cu (2 of 54)
PASS: hipify :: unit_tests/headers/headers_test_01.cu (3 of 54)
PASS: hipify :: unit_tests/headers/headers_test_05.cu (4 of 54)
PASS: hipify :: unit_tests/headers/headers_test_11.cu (5 of 54)
PASS: hipify :: unit_tests/headers/headers_test_10.cu (6 of 54)
PASS: hipify :: unit_tests/headers/headers_test_07.cu (7 of 54)
PASS: hipify :: unit_tests/headers/headers_test_06.cu (8 of 54)
PASS: hipify :: unit_tests/headers/headers_test_04.cu (9 of 54)
PASS: hipify :: unit_tests/headers/headers_test_08.cu (10 of 54)
PASS: hipify :: unit_tests/libraries/cuBLAS/cublas_sgemm_matrix_multiplication.cu (11 of 54)
PASS: hipify :: unit_tests/libraries/cuBLAS/cublas_1_based_indexing.cu (12 of 54)
PASS: hipify :: unit_tests/libraries/cuBLAS/cublas_0_based_indexing.cu (13 of 54)
PASS: hipify :: unit_tests/libraries/cuComplex/cuComplex_Julia.cu (14 of 54)
PASS: hipify :: unit_tests/libraries/CAFFE2/caffe2_02.cu (15 of 54)
PASS: hipify :: unit_tests/libraries/cuBLAS/rocBLAS/cublas_0_based_indexing_rocblas.cu (16 of 54)
PASS: hipify :: unit_tests/libraries/cuBLAS/rocBLAS/cublas_1_based_indexing_rocblas.cu (17 of 54)
PASS: hipify :: unit_tests/libraries/cuBLAS/rocBLAS/cublas_sgemm_matrix_multiplication_rocblas.cu (18 of 54)
PASS: hipify :: unit_tests/libraries/cuDNN/cudnn_softmax.cu (19 of 54)
PASS: hipify :: unit_tests/libraries/cuFFT/simple_cufft.cu (20 of 54)
PASS: hipify :: unit_tests/libraries/CAFFE2/caffe2_01.cu (21 of 54)
PASS: hipify :: unit_tests/libraries/cuRAND/poisson_api_example.cu (22 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_01.cu (23 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_02.cu (24 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_03.cu (25 of 54)
PASS: hipify :: unit_tests/libraries/cuDNN/cudnn_convolution_forward.cu (26 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_04.cu (27 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_05.cu (28 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_06.cu (29 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_07.cu (30 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_08.cu (31 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_10.cu (32 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_09.cu (33 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_11.cu (34 of 54)
PASS: hipify :: unit_tests/headers/headers_test_09.cu (35 of 54)
PASS: hipify :: unit_tests/samples/2_Cookbook/11_texture_driver/tex2dKernel.cpp (36 of 54)
PASS: hipify :: unit_tests/samples/2_Cookbook/0_MatrixTranspose/MatrixTranspose.cpp (37 of 54)
PASS: hipify :: unit_tests/samples/allocators.cu (38 of 54)
PASS: hipify :: unit_tests/samples/coalescing.cu (39 of 54)
PASS: hipify :: unit_tests/samples/2_Cookbook/11_texture_driver/texture2dDrv.cpp (40 of 54)
PASS: hipify :: unit_tests/samples/2_Cookbook/1_hipEvent/hipEvent.cpp (41 of 54)
PASS: hipify :: unit_tests/samples/2_Cookbook/2_Profiler/Profiler.cpp (42 of 54)
PASS: hipify :: unit_tests/samples/2_Cookbook/7_streams/stream.cpp (43 of 54)
PASS: hipify :: unit_tests/samples/2_Cookbook/8_peer2peer/peer2peer.cpp (44 of 54)
PASS: hipify :: unit_tests/samples/dynamic_shared_memory.cu (45 of 54)
PASS: hipify :: unit_tests/samples/axpy.cu (46 of 54)
PASS: hipify :: unit_tests/samples/intro.cu (47 of 54)
PASS: hipify :: unit_tests/libraries/cuRAND/benchmark_curand_generate.cpp (48 of 54)
PASS: hipify :: unit_tests/samples/cudaRegister.cu (49 of 54)
PASS: hipify :: unit_tests/samples/vec_add.cu (50 of 54)
PASS: hipify :: unit_tests/samples/square.cu (51 of 54)
PASS: hipify :: unit_tests/samples/static_shared_memory.cu (52 of 54)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_12.cu (53 of 54)
PASS: hipify :: unit_tests/libraries/cuRAND/benchmark_curand_kernel.cpp (54 of 54)
Testing Time: 2.92s
Expected Passes : 54
-- Testing: 58 tests, 12 threads --
PASS: hipify :: unit_tests/headers/headers_test_03.cu (1 of 58)
PASS: hipify :: unit_tests/headers/headers_test_02.cu (2 of 58)
PASS: hipify :: unit_tests/headers/headers_test_10.cu (3 of 58)
PASS: hipify :: unit_tests/headers/headers_test_05.cu (4 of 58)
PASS: hipify :: unit_tests/headers/headers_test_01.cu (5 of 58)
PASS: hipify :: unit_tests/headers/headers_test_11.cu (6 of 58)
PASS: hipify :: unit_tests/headers/headers_test_06.cu (7 of 58)
PASS: hipify :: unit_tests/headers/headers_test_07.cu (8 of 58)
PASS: hipify :: unit_tests/headers/headers_test_04.cu (9 of 58)
PASS: hipify :: unit_tests/headers/headers_test_08.cu (10 of 58)
PASS: hipify :: unit_tests/libraries/cuBLAS/cublas_1_based_indexing.cu (11 of 58)
PASS: hipify :: unit_tests/libraries/cuBLAS/rocBLAS/cublas_1_based_indexing_rocblas.cu (12 of 58)
PASS: hipify :: unit_tests/libraries/cuBLAS/cublas_0_based_indexing.cu (13 of 58)
PASS: hipify :: unit_tests/libraries/cuBLAS/cublas_sgemm_matrix_multiplication.cu (14 of 58)
PASS: hipify :: unit_tests/libraries/cuBLAS/rocBLAS/cublas_0_based_indexing_rocblas.cu (15 of 58)
PASS: hipify :: unit_tests/libraries/cuComplex/cuComplex_Julia.cu (16 of 58)
PASS: hipify :: unit_tests/libraries/CAFFE2/caffe2_02.cu (17 of 58)
PASS: hipify :: unit_tests/libraries/cuBLAS/rocBLAS/cublas_sgemm_matrix_multiplication_rocblas.cu (18 of 58)
PASS: hipify :: unit_tests/libraries/cuDNN/cudnn_softmax.cu (19 of 58)
PASS: hipify :: unit_tests/libraries/cuFFT/simple_cufft.cu (20 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_01.cu (21 of 58)
PASS: hipify :: unit_tests/libraries/CAFFE2/caffe2_01.cu (22 of 58)
PASS: hipify :: unit_tests/libraries/cuRAND/poisson_api_example.cu (23 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_02.cu (24 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_03.cu (25 of 58)
PASS: hipify :: unit_tests/libraries/cuDNN/cudnn_convolution_forward.cu (26 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_04.cu (27 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_05.cu (28 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_06.cu (29 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_07.cu (30 of 58)
PASS: hipify :: unit_tests/pp/pp_if_else_conditionals.cu (31 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_09.cu (32 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_08.cu (33 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_11.cu (34 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_10.cu (35 of 58)
PASS: hipify :: unit_tests/headers/headers_test_09.cu (36 of 58)
PASS: hipify :: unit_tests/pp/pp_if_else_conditionals_01.cu (37 of 58)
PASS: hipify :: unit_tests/samples/2_Cookbook/11_texture_driver/tex2dKernel.cpp (38 of 58)
PASS: hipify :: unit_tests/samples/MallocManaged.cpp (39 of 58)
PASS: hipify :: unit_tests/samples/2_Cookbook/0_MatrixTranspose/MatrixTranspose.cpp (40 of 58)
PASS: hipify :: unit_tests/samples/2_Cookbook/1_hipEvent/hipEvent.cpp (41 of 58)
PASS: hipify :: unit_tests/samples/2_Cookbook/2_Profiler/Profiler.cpp (42 of 58)
PASS: hipify :: unit_tests/samples/allocators.cu (43 of 58)
PASS: hipify :: unit_tests/samples/2_Cookbook/13_occupancy/occupancy.cpp (44 of 58)
PASS: hipify :: unit_tests/samples/2_Cookbook/7_streams/stream.cpp (45 of 58)
PASS: hipify :: unit_tests/samples/2_Cookbook/11_texture_driver/texture2dDrv.cpp (46 of 58)
PASS: hipify :: unit_tests/samples/2_Cookbook/8_peer2peer/peer2peer.cpp (47 of 58)
PASS: hipify :: unit_tests/libraries/cuRAND/benchmark_curand_generate.cpp (48 of 58)
PASS: hipify :: unit_tests/samples/coalescing.cu (49 of 58)
PASS: hipify :: unit_tests/samples/square.cu (50 of 58)
PASS: hipify :: unit_tests/samples/vec_add.cu (51 of 58)
PASS: hipify :: unit_tests/samples/dynamic_shared_memory.cu (52 of 58)
PASS: hipify :: unit_tests/libraries/cuRAND/benchmark_curand_kernel.cpp (53 of 58)
PASS: hipify :: unit_tests/samples/static_shared_memory.cu (54 of 58)
PASS: hipify :: unit_tests/samples/intro.cu (55 of 58)
PASS: hipify :: unit_tests/libraries/cuSPARSE/cuSPARSE_12.cu (56 of 58)
PASS: hipify :: unit_tests/samples/axpy.cu (57 of 58)
PASS: hipify :: unit_tests/samples/cudaRegister.cu (58 of 58)
Testing Time: 2.81s
Expected Passes : 58
[100%] Built target test-hipify
```
### <a name="windows"></a >Windows
@@ -317,13 +321,13 @@ On Windows 10 the following configurations are tested:
LLVM 5.0.0 - 5.0.2, CUDA 8.0, cudnn-5.1.10 - cudnn-7.1.4.18
LLVM 6.0.0 - 6.0.1, CUDA 9.0, cudnn-7.0.5.15 - cudnn-7.6.2.24
LLVM 6.0.0 - 6.0.1, CUDA 9.0, cudnn-7.0.5.15 - cudnn-7.6.3.30
LLVM 7.0.0 - 8.0.1 (with patch*), CUDA 7.5 - 10.0, cudnn-7.0.5.15 - cudnn-7.6.2.24
LLVM 7.0.0 - 8.0.1 (with patch*), CUDA 7.5 - 10.0, cudnn-7.0.5.15 - cudnn-7.6.3.30
Build system for the above configurations:
Python 3.6 (min), cmake 3.12.3 (min), Visual Studio 2017 (15.5.2) - 2019 (16.2.0).
Python 3.6 (min), cmake 3.12.3 (min), Visual Studio 2017 (15.5.2) - 2019 (16.2.3).
Here is an example of building `hipify-clang` with testing support on `Windows 10` by `Visual Studio 15 2017`:
@@ -336,7 +340,7 @@ cmake
-DCMAKE_PREFIX_PATH=f:/LLVM/6.0.1/dist \
-DCUDA_TOOLKIT_ROOT_DIR="c:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0" \
-DCUDA_SDK_ROOT_DIR="c:/ProgramData/NVIDIA Corporation/CUDA Samples/v9.0" \
-DCUDA_DNN_ROOT_DIR=f:/CUDNN/cudnn-9.0-windows10-x64-v7.6.2.24 \
-DCUDA_DNN_ROOT_DIR=f:/CUDNN/cudnn-9.0-windows10-x64-v7.6.3.30 \
-DLLVM_EXTERNAL_LIT=f:/LLVM/6.0.1/build/Release/bin/llvm-lit.py \
-Thost=x64
..
@@ -347,7 +351,7 @@ cmake
-- - CMake module path: F:/LLVM/6.0.1/dist/lib/cmake/llvm
-- - Include path : F:/LLVM/6.0.1/dist/include
-- - Binary path : F:/LLVM/6.0.1/dist/bin
-- Found PythonInterp: C:/Program Files/Python36/python.exe (found suitable version "3.7.4", minimum required is "3.6")
-- Found PythonInterp: C:/Program Files/Python37/python.exe (found suitable version "3.7.4", minimum required is "3.6")
-- Found lit: C:/Program Files/Python36/Scripts/lit.exe
-- Found FileCheck: F:/LLVM/6.0.1/dist/bin/FileCheck.exe
-- Found CUDA: C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0 (found version "9.0")
+2
Просмотреть файл
@@ -65,6 +65,8 @@ extern const std::map<llvm::StringRef, hipCounter> CUDA_SPARSE_FUNCTION_MAP;
extern const std::map<llvm::StringRef, hipCounter> CUDA_CAFFE2_TYPE_NAME_MAP;
// Maps the names of CUDA CAFFE2 API functions to the corresponding HIP functions
extern const std::map<llvm::StringRef, hipCounter> CUDA_CAFFE2_FUNCTION_MAP;
// Maps the names of CUDA Device functions to the corresponding HIP functions
extern const std::map<llvm::StringRef, hipCounter> CUDA_DEVICE_FUNC_MAP;
/**
* The union of all the above maps, except includes.
+48
Просмотреть файл
@@ -0,0 +1,48 @@
/*
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
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 "CUDA2HIP.h"
// Maps CUDA header names to HIP header names
const std::map<llvm::StringRef, hipCounter> CUDA_DEVICE_FUNC_MAP{
{"umin", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"llmin", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"ullmin", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"umax", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"llmax", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"ullmax", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__isinff", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__isnanf", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__finite", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__finitef", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__signbit", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__isnan", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__isinf", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__signbitf", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__signbitl", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__finitel", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__isinfl", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"__isnanl", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"_ldsign", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"_fdsign", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
{"_Pow_int", {"", "", CONV_DEVICE_FUNC, API_RUNTIME, UNSUPPORTED}},
};
+35 -5
Просмотреть файл
@@ -67,7 +67,6 @@ void HipifyAction::RewriteString(StringRef s, clang::SourceLocation start) {
* Otherwise, the source file is updated with the corresponding hipification.
*/
void HipifyAction::RewriteToken(const clang::Token& t) {
clang::SourceManager& SM = getCompilerInstance().getSourceManager();
// String literals containing CUDA references need fixing.
if (t.is(clang::tok::string_literal)) {
StringRef s(t.getLiteralData(), t.getLength());
@@ -78,13 +77,19 @@ void HipifyAction::RewriteToken(const clang::Token& t) {
return;
}
StringRef name = t.getRawIdentifier();
const auto found = CUDA_RENAMES_MAP().find(name);
if (found == CUDA_RENAMES_MAP().end()) {
clang::SourceLocation sl = t.getLocation();
FindAndReplace(name, sl, CUDA_RENAMES_MAP());
}
void HipifyAction::FindAndReplace(llvm::StringRef name,
clang::SourceLocation sl,
const std::map<llvm::StringRef, hipCounter>& repMap) {
const auto found = repMap.find(name);
if (found == repMap.end()) {
// So it's an identifier, but not CUDA? Boring.
return;
}
Statistics::current().incrementCounter(found->second, name.str());
clang::SourceLocation sl = t.getLocation();
clang::DiagnosticsEngine& DE = getCompilerInstance().getDiagnostics();
// Warn the user about unsupported identifier.
if (Statistics::isUnsupported(found->second)) {
@@ -96,6 +101,7 @@ void HipifyAction::RewriteToken(const clang::Token& t) {
return;
}
StringRef repName = Statistics::isToRoc(found->second) ? found->second.rocName : found->second.hipName;
clang::SourceManager& SM = getCompilerInstance().getSourceManager();
ct::Replacement Rep(SM, sl, name.size(), repName.str());
clang::FullSourceLoc fullSL(sl, SM);
insertReplacement(Rep, fullSL);
@@ -372,6 +378,14 @@ bool HipifyAction::cudaSharedIncompleteArrayVar(const clang::ast_matchers::Match
return true;
}
bool HipifyAction::cudaDeviceFuncCall(const clang::ast_matchers::MatchFinder::MatchResult& Result) {
if (const clang::CallExpr *call = Result.Nodes.getNodeAs<clang::CallExpr>("cudaDeviceFuncCall")) {
const clang::FunctionDecl *funcDcl = call->getDirectCallee();
FindAndReplace(funcDcl->getDeclName().getAsString(), llcompat::getBeginLoc(call), CUDA_DEVICE_FUNC_MAP);
}
return true;
}
void HipifyAction::insertReplacement(const ct::Replacement& rep, const clang::FullSourceLoc& fullSL) {
llcompat::insertReplacement(*replacements, rep);
if (PrintStats) {
@@ -395,7 +409,22 @@ std::unique_ptr<clang::ASTConsumer> HipifyAction::CreateASTConsumer(clang::Compi
).bind("cudaSharedIncompleteArrayVar"),
this
);
// Ownership is transferred to the caller...
Finder->addMatcher(
mat::callExpr(
mat::isExpansionInMainFile(),
mat::callee(
mat::functionDecl(
mat::anyOf(
mat::hasAttr(clang::attr::CUDADevice),
mat::hasAttr(clang::attr::CUDAGlobal)
),
mat::unless(mat::hasAttr(clang::attr::CUDAHost))
)
)
).bind("cudaDeviceFuncCall"),
this
);
// Ownership is transferred to the caller.
return Finder->newASTConsumer();
}
@@ -517,4 +546,5 @@ void HipifyAction::ExecuteAction() {
void HipifyAction::run(const clang::ast_matchers::MatchFinder::MatchResult& Result) {
if (cudaLaunchKernel(Result)) return;
if (cudaSharedIncompleteArrayVar(Result)) return;
if (cudaDeviceFuncCall(Result)) return;
}
+2
Просмотреть файл
@@ -70,6 +70,7 @@ public:
bool cudaBuiltin(const clang::ast_matchers::MatchFinder::MatchResult& Result);
bool cudaLaunchKernel(const clang::ast_matchers::MatchFinder::MatchResult& Result);
bool cudaSharedIncompleteArrayVar(const clang::ast_matchers::MatchFinder::MatchResult& Result);
bool cudaDeviceFuncCall(const clang::ast_matchers::MatchFinder::MatchResult& Result);
// Called by the preprocessor for each include directive during the non-raw lexing pass.
void InclusionDirective(clang::SourceLocation hash_loc,
const clang::Token &include_token,
@@ -99,4 +100,5 @@ protected:
void run(const clang::ast_matchers::MatchFinder::MatchResult& Result) override;
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &CI, llvm::StringRef InFile) override;
bool Exclude(const hipCounter & hipToken);
void FindAndReplace(llvm::StringRef name, clang::SourceLocation sl, const std::map<llvm::StringRef, hipCounter>& repMap);
};
+6
Просмотреть файл
@@ -43,7 +43,13 @@ public:
ct::FrontendActionFactory(),
replacements(r) {}
#if LLVM_VERSION_MAJOR < 10
clang::FrontendAction* create() override {
return new T(replacements);
}
#else
std::unique_ptr <clang::FrontendAction> create() override {
return std::unique_ptr<clang::FrontendAction>(new T(replacements));
}
#endif
};
+1
Просмотреть файл
@@ -57,6 +57,7 @@ const char *counterNames[NUM_CONV_TYPES] = {
"complex", // CONV_COMPLEX
"library", // CONV_LIB_FUNC
"device_library", // CONV_LIB_DEVICE_FUNC
"device_function", // CONV_DEVICE_FUNC
"include", // CONV_INCLUDE
"include_cuda_main_header", // CONV_INCLUDE_CUDA_MAIN_H
"type", // CONV_TYPE
+1
Просмотреть файл
@@ -112,6 +112,7 @@ enum ConvTypes {
CONV_COMPLEX,
CONV_LIB_FUNC,
CONV_LIB_DEVICE_FUNC,
CONV_DEVICE_FUNC,
CONV_INCLUDE,
CONV_INCLUDE_CUDA_MAIN_H,
CONV_TYPE,
+1 -1
Просмотреть файл
@@ -970,7 +970,7 @@ static void __barrier(int n)
__device__
inline
__attribute__((noduplicate))
__attribute__((convergent))
void __syncthreads()
{
__barrier(__CLK_LOCAL_MEM_FENCE);
+2 -5
Просмотреть файл
@@ -331,11 +331,6 @@ extern void ihipPostLaunchKernel(const char* kernelName, hipStream_t stream, gri
typedef int hipLaunchParm;
#define hipLaunchKernel(kernelName, numblocks, numthreads, memperblock, streamId, ...) \
do { \
kernelName<<<(numblocks), (numthreads), (memperblock), (streamId)>>>(hipLaunchParm{}, ##__VA_ARGS__); \
} while (0)
#define hipLaunchKernelGGL(kernelName, numblocks, numthreads, memperblock, streamId, ...) \
do { \
kernelName<<<(numblocks), (numthreads), (memperblock), (streamId)>>>(__VA_ARGS__); \
@@ -452,6 +447,7 @@ hc_get_workitem_absolute_id(int dim)
#endif
// Support std::complex.
#ifndef _OPENMP
#pragma push_macro("__CUDA__")
#define __CUDA__
#include <__clang_cuda_math_forward_declares.h>
@@ -461,6 +457,7 @@ hc_get_workitem_absolute_id(int dim)
#include <cuda_wrappers/new>
#undef __CUDA__
#pragma pop_macro("__CUDA__")
#endif // ndef _OPENMP
#if __HIP_VDI__
hipError_t hipExtModuleLaunchKernel(hipFunction_t f, uint32_t globalWorkSizeX,
+11 -2
Просмотреть файл
@@ -220,8 +220,17 @@ TidInfo::TidInfo() : _apiSeqNum(0) {
tid_ss_num << std::this_thread::get_id();
tid_ss << std::hex << std::stoull(tid_ss_num.str());
tprintf(DB_API, "HIP initialized short_tid#%d (maps to full_tid: 0x%s)\n", _shortTid,
tid_ss.str().c_str());
// cannot use tprintf here since it will recurse back into TlsData constructor
#if COMPILE_HIP_DB
if (HIP_DB & (1 << DB_API)) {
char msgStr[1000];
snprintf(msgStr, sizeof(msgStr),
"HIP initialized short_tid#%d (maps to full_tid: 0x%s)\n",
tid(), tid_ss.str().c_str());
fprintf(stderr, " %ship-%s pid:%d tid:%d:%s%s", dbName[DB_API]._color,
dbName[DB_API]._shortName, pid(), tid(), msgStr, KNRM);
}
#endif
};
}
-7
Просмотреть файл
@@ -1557,13 +1557,6 @@ hipError_t ihipMemPtrGetInfo(void* ptr, size_t* size) {
template <typename T>
void ihipMemsetKernel(hipStream_t stream, T* ptr, T val, size_t count) {
// Just Use count, instead of dividing by 4, the calling API already does it
if (sizeof(T) == sizeof(uint32_t) && (count % sizeof(uint32_t) == 0) &&
!hsa_amd_memory_fill(ptr, reinterpret_cast<const std::uint32_t&>(val), count)) {
// Only return if the execution completes without error
// if error occured, try the normal version
return;
}
static constexpr uint32_t block_dim = 256;
const uint32_t grid_dim = clamp_integer<size_t>(count / block_dim, 1, UINT32_MAX);
+46
Просмотреть файл
@@ -0,0 +1,46 @@
// RUN: %run_test hipify "%s" "%t" %hipify_args %clang_args
// Test to warn only on device functions umin and umax as unsupported, but not on user defined ones.
// ToDo: change lit testing in order to parse the output.
#define LEN 1024
#define SIZE LEN * sizeof(float)
// CHECK: #include <hip/hip_runtime.h>
#include <algorithm>
namespace my {
unsigned int umin(unsigned int arg1, unsigned int arg2) {
return (arg1 < arg2) ? arg1 : arg2;
}
unsigned int umax(unsigned int arg1, unsigned int arg2) {
return (arg1 > arg2) ? arg1 : arg2;
}
}
__global__ void uint_arithm(float* A, float* B, float* C, unsigned int u1, unsigned int u2)
{
unsigned int _umin = umin(u1, u2);
unsigned int _umax = umax(u1, u2);
int i = threadIdx.x;
A[i] = i + _umin;
B[i] = i + _umax;
C[i] = A[i] + B[i];
}
int main() {
unsigned int u1 = 33;
unsigned int u2 = 34;
unsigned int _min = my::umin(u1, u2);
unsigned int _max = my::umax(u1, u2);
float *A, *B, *C;
// CHECK: hipMalloc((void**)&A, SIZE);
cudaMalloc((void**)&A, SIZE);
// CHECK: hipMalloc((void**)&B, SIZE);
cudaMalloc((void**)&B, SIZE);
// CHECK: hipMalloc((void**)&C, SIZE);
cudaMalloc((void**)&C, SIZE);
dim3 dimGrid(LEN / 512, 1, 1);
dim3 dimBlock(512, 1, 1);
// CHECK: hipLaunchKernelGGL(uint_arithm, dim3(dimGrid), dim3(dimBlock), 0, 0, A, B, C, u1, u2);
uint_arithm<<<dimGrid, dimBlock>>>(A, B, C, u1, u2);
return _min < _max;
}
+198
Просмотреть файл
@@ -0,0 +1,198 @@
// RUN: %run_test hipify "%s" "%t" %hipify_args %clang_args
/*
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
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 WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// CHECK: #include "hip/hip_runtime.h"
#include "cuda_runtime.h"
#include <iostream>
#define NUM 1000000
// CHECK: if (status != hipSuccess) {
#define CUDA_CHECK(status) \
if (status != cudaSuccess) { \
std::cout << "Got Status: " << status << " at Line: " << __LINE__ << std::endl; \
exit(0); \
}
// Device (Kernel) function
__global__ void multiply(float* C, float* A, float* B, int N) {
int tx = blockDim.x*blockIdx.x+threadIdx.x;
if (tx < N) {
C[tx] = A[tx] * B[tx];
}
}
// CPU implementation
void multiplyCPU(float* C, float* A, float* B, int N) {
for(unsigned int i=0; i<N; i++) {
C[i] = A[i] * B[i];
}
}
void launchKernel(float* C, float* A, float* B, bool manual) {
// CHECK: hipDeviceProp_t devProp;
cudaDeviceProp devProp;
// CHECK: CUDA_CHECK(hipGetDeviceProperties(&devProp, 0));
CUDA_CHECK(cudaGetDeviceProperties(&devProp, 0));
// CHECK: hipEvent_t start, stop;
cudaEvent_t start, stop;
// CHECK: CUDA_CHECK(hipEventCreate(&start));
CUDA_CHECK(cudaEventCreate(&start));
// CHECK: CUDA_CHECK(hipEventCreate(&stop));
CUDA_CHECK(cudaEventCreate(&stop));
float eventMs = 1.0f;
const unsigned threadsperblock = 32;
const unsigned blocks = (NUM/threadsperblock) + 1;
int mingridSize = 0;
int gridSize = 0;
int blockSize = 0;
if (manual) {
blockSize = threadsperblock;
gridSize = blocks;
std::cout << std::endl << "Manual Configuration with block size " << blockSize << std::endl;
} else {
// CHECK: CUDA_CHECK(hipOccupancyMaxPotentialBlockSize(&mingridSize, &blockSize, multiply, 0, 0));
CUDA_CHECK(cudaOccupancyMaxPotentialBlockSize(&mingridSize, &blockSize, multiply, 0, 0));
std::cout << std::endl << "Automatic Configuation based on hipOccupancyMaxPotentialBlockSize " << std::endl;
std::cout << "Suggested blocksize is " << blockSize << ", Minimum gridsize is " << mingridSize << std::endl;
gridSize = (NUM/blockSize)+1;
}
// Record the start event
// CHECK: CUDA_CHECK(hipEventRecord(start, NULL));
CUDA_CHECK(cudaEventRecord(start, NULL));
// Launching the Kernel from Host
// CHECK: hipLaunchKernelGGL(multiply, dim3(gridSize), dim3(blockSize), 0, 0, C, A, B, NUM);
multiply <<<gridSize , blockSize>>> (C, A, B, NUM);
// Record the stop event
// CHECK: CUDA_CHECK(hipEventRecord(stop, NULL));
CUDA_CHECK(cudaEventRecord(stop, NULL));
// CHECK: CUDA_CHECK(hipEventSynchronize(stop));
CUDA_CHECK(cudaEventSynchronize(stop));
// CHECK: CUDA_CHECK(hipEventElapsedTime(&eventMs, start, stop));
CUDA_CHECK(cudaEventElapsedTime(&eventMs, start, stop));
printf("kernel Execution time = %6.3fms\n", eventMs);
// Calculate Occupancy
int numBlock = 0;
// CHECK: CUDA_CHECK(hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, multiply, blockSize, 0));
CUDA_CHECK(cudaOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, multiply, blockSize, 0));
if(devProp.maxThreadsPerMultiProcessor) {
std::cout << "Theoretical Occupancy is " << (double)numBlock* blockSize/devProp.maxThreadsPerMultiProcessor * 100 << "%" << std::endl;
}
}
int main() {
float *A, *B, *C0, *C1, *cpuC;
float *Ad, *Bd, *C0d, *C1d;
int errors=0;
// Initialize the input data
A = (float*)malloc(NUM * sizeof(float));
B = (float*)malloc(NUM * sizeof(float));
C0 = (float*)malloc(NUM * sizeof(float));
C1 = (float*)malloc(NUM * sizeof(float));
cpuC = (float*)malloc(NUM * sizeof(float));
for(int i=0; i< NUM; i++) {
A[i] = i;
B[i] = i;
}
// Allocate the memory on the device side
// CHECK: CUDA_CHECK(hipMalloc((void**)&Ad, NUM * sizeof(float)));
CUDA_CHECK(cudaMalloc((void**)&Ad, NUM * sizeof(float)));
// CHECK: CUDA_CHECK(hipMalloc((void**)&Bd, NUM * sizeof(float)));
CUDA_CHECK(cudaMalloc((void**)&Bd, NUM * sizeof(float)));
// CHECK: CUDA_CHECK(hipMalloc((void**)&C0d, NUM * sizeof(float)));
CUDA_CHECK(cudaMalloc((void**)&C0d, NUM * sizeof(float)));
// CHECK: CUDA_CHECK(hipMalloc((void**)&C1d, NUM * sizeof(float)));
CUDA_CHECK(cudaMalloc((void**)&C1d, NUM * sizeof(float)));
// Memory transfer from host to device
// CHECK: CUDA_CHECK(hipMemcpy(Ad,A,NUM * sizeof(float), hipMemcpyHostToDevice));
CUDA_CHECK(cudaMemcpy(Ad,A,NUM * sizeof(float), cudaMemcpyHostToDevice));
// CHECK: CUDA_CHECK(hipMemcpy(Bd,B,NUM * sizeof(float), hipMemcpyHostToDevice));
CUDA_CHECK(cudaMemcpy(Bd,B,NUM * sizeof(float), cudaMemcpyHostToDevice));
// Kernel launch with manual/default block size
launchKernel(C0d, Ad, Bd, 1);
// Kernel launch with the block size suggested by cudaOccupancyMaxPotentialBlockSize
launchKernel(C1d, Ad, Bd, 0);
// Memory transfer from device to host
// CHECK: CUDA_CHECK(hipMemcpy(C0,C0d, NUM * sizeof(float), hipMemcpyDeviceToHost));
CUDA_CHECK(cudaMemcpy(C0,C0d, NUM * sizeof(float), cudaMemcpyDeviceToHost));
// CHECK: CUDA_CHECK(hipMemcpy(C1,C1d, NUM * sizeof(float), hipMemcpyDeviceToHost));
CUDA_CHECK(cudaMemcpy(C1,C1d, NUM * sizeof(float), cudaMemcpyDeviceToHost));
// CPU computation
multiplyCPU(cpuC, A, B, NUM);
// Verify the results
double eps = 1.0E-6;
for (int i = 0; i < NUM; i++) {
if (std::abs(C0[i] - cpuC[i]) > eps) {
errors++;
}
}
if (errors != 0) {
printf("\nManual Test FAILED: %d errors\n", errors);
errors=0;
} else {
printf("\nManual Test PASSED!\n");
}
for (int i = 0; i < NUM; i++) {
if (std::abs(C1[i] - cpuC[i]) > eps) {
errors++;
}
}
if (errors != 0) {
printf("\n Automatic Test FAILED: %d errors\n", errors);
} else {
printf("\nAutomatic Test PASSED!\n");
}
// CHECK: CUDA_CHECK(hipFree(Ad));
CUDA_CHECK(cudaFree(Ad));
// CHECK: CUDA_CHECK(hipFree(Bd));
CUDA_CHECK(cudaFree(Bd));
// CHECK: CUDA_CHECK(hipFree(C0d));
CUDA_CHECK(cudaFree(C0d));
// CHECK: CUDA_CHECK(hipFree(C1d));
CUDA_CHECK(cudaFree(C1d));
free(A);
free(B);
free(C0);
free(C1);
free(cpuC);
}
+11
Просмотреть файл
@@ -19,6 +19,8 @@ __global__ void axpy(T a, T *x, T *y) {
y[threadIdx.x] = a * x[threadIdx.x];
}
__global__ void empty() {
}
int main(int argc, char* argv[]) {
const int kDataLen = 4;
@@ -64,6 +66,15 @@ int main(int argc, char* argv[]) {
// CHECK: hipLaunchKernelGGL(axpy<float>, dim3(1), dim3(kDataLen), 0, 0, ARG_LIST_AS_MACRO);
KERNEL_CALL_AS_MACRO(ARG_LIST_AS_MACRO);
// CHECK: hipLaunchKernelGGL(empty, dim3(1), dim3(kDataLen), 0, 0);
empty<<<1, kDataLen>>> ( );
// CHECK: hipLaunchKernelGGL(empty, dim3(1), dim3(kDataLen), 0, 0);
empty<<<1, kDataLen, 0>>>();
// CHECK: hipLaunchKernelGGL(empty, dim3(1), dim3(kDataLen), 0, 0);
empty<<<1, kDataLen, 0, 0>>>();
// CHECK: COMPLETE_LAUNCH;
COMPLETE_LAUNCH;
-713
Просмотреть файл
@@ -1,713 +0,0 @@
/*
Copyright (c) 2018 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.
*/
/*
* HIT_START
* BUILD: %t %s ../test_common.cpp HIPCC_OPTIONS -std=c++11 EXCLUDE_HIP_PLATFORM nvcc
* TEST: %t
* HIT_END
*/
// Includes HIP Runtime
#include "hip/hip_runtime.h"
#include <test_common.h>
#include <set>
#include <unordered_map>
#define test_failed(test_name) \
printf("%s %s FAILED!%s\n", KRED, test_name, KNRM);
#define test_passed(test_name) \
printf("%s %s PASSED!%s\n", KGRN, test_name, KNRM);
/* BEGIN DUPLICATION */
// TODO: The host code below is duplicated, and should ideally reside
// in a common host-side library.
typedef enum {
__OCKL_AS_PACKET_EMPTY = 0,
__OCKL_AS_PACKET_READY = 1
} __ockl_as_packet_type_t;
#define __OCKL_AS_PAYLOAD_ALIGNMENT 4
#define __OCKL_AS_PAYLOAD_BYTES 48
typedef enum {
__OCKL_AS_PACKET_HEADER_TYPE = 0, // corresponds to HSA_PACKET_HEADER_TYPE
__OCKL_AS_PACKET_HEADER_RESERVED0 = 8,
__OCKL_AS_PACKET_HEADER_FLAGS = 13,
__OCKL_AS_PACKET_HEADER_BYTES = 16,
__OCKL_AS_PACKET_HEADER_SERVICE = 24,
} __ockl_as_packet_header_t;
typedef enum {
__OCKL_AS_PACKET_HEADER_WIDTH_TYPE = 8,
__OCKL_AS_PACKET_HEADER_WIDTH_RESERVED0 = 5,
__OCKL_AS_PACKET_HEADER_WIDTH_FLAGS = 3,
__OCKL_AS_PACKET_HEADER_WIDTH_BYTES = 8,
__OCKL_AS_PACKET_HEADER_WIDTH_SERVICE = 8
} __ockl_as_packet_header_width_t;
// A packet is 64 bytes long, and the payload starts at index 16.
struct __ockl_as_packet_t {
uint header;
uint reserved1;
ulong connection_id;
uchar payload[__OCKL_AS_PAYLOAD_BYTES];
};
typedef enum {
__OCKL_AS_STATUS_SUCCESS,
__OCKL_AS_STATUS_INVALID_REQUEST,
__OCKL_AS_STATUS_OUT_OF_RESOURCES,
__OCKL_AS_STATUS_BUSY,
__OCKL_AS_STATUS_UNKNOWN_ERROR
} __ockl_as_status_t;
typedef enum {
__OCKL_AS_CONNECTION_BEGIN = 1,
__OCKL_AS_CONNECTION_END = 2,
} __ockl_as_flag_t;
typedef enum { __OCKL_AS_FEATURE_ASYNCHRONOUS = 1 } __ockl_as_feature_t;
typedef struct {
// Opaque handle. The value 0 is reserved.
ulong handle;
} __ockl_as_signal_t;
typedef struct __ockl_as_packet_t __ockl_as_packet_t;
typedef struct {
ulong read_index;
ulong write_index;
__ockl_as_signal_t doorbell_signal;
__ockl_as_packet_t *base_address;
ulong size;
} __ockl_as_stream_t;
#define ATTR_GLOBAL __attribute__((address_space(1)))
extern "C" __device__ __ockl_as_status_t
__ockl_as_write_block(__ockl_as_stream_t ATTR_GLOBAL *stream, uchar service_id,
uint64_t *connection_id, const uchar *str, uint32_t len,
uchar flags);
__device__ __ockl_as_status_t
__hip_as_write_block(__ockl_as_stream_t *stream, uchar service_id,
uint64_t *connection_id, const uchar *str, uint32_t len,
uchar flags)
{
__ockl_as_stream_t ATTR_GLOBAL *gstream =
(__ockl_as_stream_t ATTR_GLOBAL *)(stream);
return __ockl_as_write_block(gstream, service_id, connection_id, str, len,
flags);
}
/* END DUPLICATION */
static __ockl_as_stream_t *
createStream(void *ptr, uint buffer_size, uint num_packets)
{
memset(ptr, 0, buffer_size);
__ockl_as_stream_t *r = (__ockl_as_stream_t *)ptr;
r->base_address = (__ockl_as_packet_t *)(&r[1]);
r->doorbell_signal = {0};
r->size = num_packets;
return r;
}
static uint8_t
get_header_field(uint32_t header, uint8_t offset, uint8_t size)
{
return (header >> offset) & ((1 << size) - 1);
}
static uint8_t
get_packet_type(uint32_t header)
{
return get_header_field(header, __OCKL_AS_PACKET_HEADER_TYPE,
__OCKL_AS_PACKET_HEADER_WIDTH_TYPE);
}
static uint8_t
get_packet_flags(uint32_t header)
{
return get_header_field(header, __OCKL_AS_PACKET_HEADER_FLAGS,
__OCKL_AS_PACKET_HEADER_WIDTH_FLAGS);
}
static uint8_t
get_packet_bytes(uint32_t header)
{
return get_header_field(header, __OCKL_AS_PACKET_HEADER_BYTES,
__OCKL_AS_PACKET_HEADER_WIDTH_BYTES);
}
static uint8_t
get_packet_service(uint32_t header)
{
return get_header_field(header, __OCKL_AS_PACKET_HEADER_SERVICE,
__OCKL_AS_PACKET_HEADER_WIDTH_SERVICE);
}
const unsigned int __OCKL_AS_PACKET_SIZE = sizeof(__ockl_as_packet_t);
/* END DUPLICATION */
using namespace std;
#define STR_HELLO_WORLD "hello world"
#define STRLEN_HELLO_WORLD 11
const unsigned int THREADS_PER_BLOCK = 123; // include a partial warp
const unsigned int NUM_BLOCKS = 3; // because powers of two are too convenient
const unsigned int NUM_THREADS = NUM_BLOCKS * THREADS_PER_BLOCK;
const unsigned int NUM_PACKETS_INSUFFICIENT = NUM_THREADS - 23;
const unsigned int NUM_PACKETS_LARGE = NUM_THREADS * 4;
const unsigned int NUM_SERVICES = 7;
const unsigned int TEST_SERVICE = 42;
unsigned int
read_uint(const unsigned char *ptr)
{
unsigned int value = 0;
for (int ii = sizeof(unsigned int) - 1; ii >= 0; --ii) {
value <<= 8;
value |= ptr[ii];
}
return value;
}
__global__ void
singlePacketSingleProducer(__ockl_as_stream_t *stream)
{
uint len = STRLEN_HELLO_WORLD;
uint64_t connection_id;
__hip_as_write_block(stream, TEST_SERVICE, &connection_id,
(const uint8_t *)STR_HELLO_WORLD, STRLEN_HELLO_WORLD,
__OCKL_AS_CONNECTION_BEGIN | __OCKL_AS_CONNECTION_END);
}
bool
checkSinglePacketSingleProducer(__ockl_as_stream_t *stream)
{
if (stream->write_index != 1)
return false;
__ockl_as_packet_t *packet = &stream->base_address[0];
uint header = packet->header;
if (get_packet_type(header) != __OCKL_AS_PACKET_READY)
return false;
if (get_packet_service(header) != TEST_SERVICE)
return false;
if (get_packet_bytes(header) != STRLEN_HELLO_WORLD)
return false;
if (get_packet_flags(header) !=
(__OCKL_AS_CONNECTION_BEGIN | __OCKL_AS_CONNECTION_END))
return false;
if (0 != strcmp(STR_HELLO_WORLD, (const char *)packet->payload))
return false;
return true;
}
bool
ocklAsSinglePacketSingleProducer()
{
bool success = true;
unsigned int numThreads = 1;
unsigned int numBlocks = 1;
unsigned int numPackets = 1;
unsigned int bufferSize =
sizeof(__ockl_as_stream_t) + numPackets * __OCKL_AS_PACKET_SIZE;
void *buffer;
HIPCHECK(hipHostMalloc(&buffer, bufferSize));
__ockl_as_stream_t *stream = createStream(buffer, bufferSize, numPackets);
hipLaunchKernelGGL(singlePacketSingleProducer, dim3(numBlocks),
dim3(numThreads), 0, 0, stream);
HIPCHECK(hipDeviceSynchronize());
if (!checkSinglePacketSingleProducer(stream)) {
test_failed(__func__);
success = false;
}
HIPCHECK(hipHostFree(buffer));
return success;
}
__global__ void
multipleProducers(__ockl_as_stream_t *stream)
{
const unsigned int tid = blockDim.x * blockIdx.x + threadIdx.x;
unsigned char data = (unsigned char)tid;
uint64_t connection_id;
__hip_as_write_block(stream, tid % NUM_SERVICES, &connection_id,
(const unsigned char *)&tid, sizeof(unsigned int),
__OCKL_AS_CONNECTION_BEGIN | __OCKL_AS_CONNECTION_END);
}
bool
checkMultipleProducers(__ockl_as_stream_t *stream)
{
int data[NUM_SERVICES] = {
0,
};
if (stream->write_index != NUM_THREADS)
return false;
for (int ii = 0; ii != NUM_THREADS; ++ii) {
__ockl_as_packet_t *packet = &stream->base_address[ii];
uint header = packet->header;
if (get_packet_type(header) != __OCKL_AS_PACKET_READY)
return false;
if (get_packet_bytes(header) != sizeof(unsigned int))
return false;
if (get_packet_flags(header) !=
(__OCKL_AS_CONNECTION_BEGIN | __OCKL_AS_CONNECTION_END))
return false;
unsigned char service = get_packet_service(header);
unsigned int payload = read_uint(packet->payload);
if (service != payload % NUM_SERVICES)
return false;
data[service]++;
}
int expected[NUM_SERVICES];
for (int ii = 0; ii != NUM_SERVICES; ++ii) {
expected[ii] = NUM_THREADS / NUM_SERVICES;
if (ii < NUM_THREADS % NUM_SERVICES) {
expected[ii]++;
}
}
for (int ii = 0; ii != NUM_SERVICES; ++ii) {
if (data[ii] != expected[ii])
return false;
}
return true;
}
bool
ocklAsMultipleProducers()
{
bool success = true;
unsigned int numPackets = NUM_THREADS;
unsigned int bufferSize =
sizeof(__ockl_as_stream_t) + numPackets * __OCKL_AS_PACKET_SIZE;
void *buffer;
HIPCHECK(hipHostMalloc(&buffer, bufferSize));
__ockl_as_stream_t *stream = createStream(buffer, bufferSize, numPackets);
hipLaunchKernelGGL(multipleProducers, dim3(NUM_BLOCKS),
dim3(THREADS_PER_BLOCK), 0, 0, stream);
HIPCHECK(hipDeviceSynchronize());
if (!checkMultipleProducers(stream)) {
test_failed(__func__);
success = false;
}
HIPCHECK(hipHostFree(buffer));
return success;
}
__global__ void
dropPackets(__ockl_as_stream_t *stream, unsigned int *status)
{
const unsigned int tid = blockDim.x * blockIdx.x + threadIdx.x;
uint64_t connection_id;
status[tid] =
__hip_as_write_block(stream, TEST_SERVICE, &connection_id,
(const unsigned char *)&tid, sizeof(unsigned int),
__OCKL_AS_CONNECTION_BEGIN |
__OCKL_AS_CONNECTION_END);
}
bool
checkDropPackets(__ockl_as_stream_t *stream, unsigned int *status)
{
unsigned int errorsExpected = NUM_THREADS - NUM_PACKETS_INSUFFICIENT;
for (int ii = 0; ii != NUM_THREADS; ++ii) {
switch (status[ii]) {
case __OCKL_AS_STATUS_OUT_OF_RESOURCES:
if (errorsExpected == 0)
return false;
--errorsExpected;
break;
case __OCKL_AS_STATUS_SUCCESS:
break;
default:
return false;
}
}
if (errorsExpected != 0)
return false;
if (stream->write_index != NUM_PACKETS_INSUFFICIENT)
return false;
for (int ii = 0; ii != NUM_PACKETS_INSUFFICIENT; ++ii) {
__ockl_as_packet_t *packet = &stream->base_address[ii];
uint header = packet->header;
if (get_packet_type(header) != __OCKL_AS_PACKET_READY)
return false;
if (get_packet_service(header) != TEST_SERVICE)
return false;
if (get_packet_bytes(header) != sizeof(unsigned int))
return false;
if (get_packet_flags(header) !=
(__OCKL_AS_CONNECTION_BEGIN | __OCKL_AS_CONNECTION_END))
return false;
unsigned int payload = read_uint(packet->payload);
if (payload >= NUM_THREADS)
return false;
}
return true;
}
bool
ocklAsDropPackets()
{
bool success = true;
unsigned int numPackets = NUM_PACKETS_INSUFFICIENT;
unsigned int bufferSize =
sizeof(__ockl_as_stream_t) + numPackets * __OCKL_AS_PACKET_SIZE;
void *buffer;
HIPCHECK(hipHostMalloc(&buffer, bufferSize));
void *status;
HIPCHECK(hipHostMalloc(&status, NUM_THREADS * sizeof(unsigned int)));
__ockl_as_stream_t *stream = createStream(buffer, bufferSize, numPackets);
hipEvent_t event;
HIPCHECK(hipEventCreate(&event));
hipLaunchKernelGGL(dropPackets, dim3(NUM_BLOCKS), dim3(THREADS_PER_BLOCK),
0, 0, stream, (unsigned int *)status);
HIPCHECK(hipDeviceSynchronize());
if (!checkDropPackets(stream, (unsigned int *)status)) {
test_failed(__func__);
success = false;
}
HIPCHECK(hipHostFree(buffer));
return success;
}
#define STR30 "Cras nec volutpat mi, sed sed."
#define STR47 "Lorem ipsum dolor sit amet, consectetur nullam."
#define STR60 "Curabitur id maximus nibh. Donec quis porttitor nisl nullam."
#define STR95 \
"In mollis imperdiet nibh nec ullamcorper." \
" Suspendisse placerat massa iaculis ipsum viverra sed."
#define STR124 \
"Proin ut diam sit amet erat mollis gravida ac non sem." \
" Mauris viverra leo metus, id luctus metus feugiat sed. Morbi " \
"posuere."
#define DECLARE_TEST_DATA() \
const char *str30 = STR30; \
const char *str60 = STR60; \
const char *str47 = STR47; \
const char *str95 = STR95; \
const char *str124 = STR124; \
const int numStr = 5; \
const char *strArray[5] = {str30, str60, str47, str95, str124}; \
unsigned char strLengths[5] = {30, 60, 47, 95, 124};
__global__ void
mixedProducers(__ockl_as_stream_t *stream)
{
DECLARE_TEST_DATA();
const unsigned int tid = blockDim.x * blockIdx.x + threadIdx.x;
const unsigned int idx = tid % 5;
uint64_t connection_id;
__hip_as_write_block(stream, idx, &connection_id,
(unsigned const char *)strArray[idx], strLengths[idx],
__OCKL_AS_CONNECTION_BEGIN | __OCKL_AS_CONNECTION_END);
}
bool
checkMixedProducers(__ockl_as_stream_t *stream)
{
typedef std::unordered_map<uint64_t, std::string> stream_buffer_map_t;
stream_buffer_map_t buffers;
std::unordered_map<std::string, int> strRecd;
DECLARE_TEST_DATA();
for (unsigned long read_index = 0; read_index != stream->write_index;
++read_index) {
__ockl_as_packet_t *packet = stream->base_address + read_index;
uint header = packet->header;
if (get_packet_type(header) != __OCKL_AS_PACKET_READY)
return false;
uint bytes = get_packet_bytes(header);
unsigned char flags = get_packet_flags(header);
unsigned char service = get_packet_service(header);
unsigned long connection_id = packet->connection_id;
unsigned char *payload = packet->payload;
if ((flags & __OCKL_AS_CONNECTION_BEGIN) !=
(buffers.count(connection_id) == 0))
return false;
std::string &buf = buffers[connection_id];
buf.insert(buf.end(), payload, payload + bytes);
if (flags & __OCKL_AS_CONNECTION_END) {
if (buf != strArray[service])
return false;
strRecd[buf]++;
buffers.erase(connection_id);
}
}
int expected_counts[numStr];
for (int ii = 0; ii != numStr; ++ii) {
expected_counts[ii] = NUM_THREADS / numStr;
if (ii < (NUM_THREADS % numStr)) {
++expected_counts[ii];
}
}
if (strRecd.size() != numStr)
return false;
for (int ii = 0; ii != numStr; ++ii) {
std::string mystr(strArray[ii]);
if (strRecd[mystr] != expected_counts[ii])
return false;
}
return true;
}
bool
ocklAsMixedProducers()
{
bool success = true;
unsigned int numPackets = NUM_PACKETS_LARGE;
unsigned int bufferSize =
sizeof(__ockl_as_stream_t) + numPackets * __OCKL_AS_PACKET_SIZE;
void *buffer;
HIPCHECK(hipHostMalloc(&buffer, bufferSize));
__ockl_as_stream_t *stream = createStream(buffer, bufferSize, numPackets);
hipLaunchKernelGGL(mixedProducers, dim3(NUM_BLOCKS),
dim3(THREADS_PER_BLOCK), 0, 0, stream);
HIPCHECK(hipDeviceSynchronize());
if (!checkMixedProducers(stream)) {
test_failed(__func__);
success = false;
}
HIPCHECK(hipHostFree(buffer));
return success;
}
#define STR27 "In et consectetur mi metus."
#define STR64 "Praesent tempus arcu id ligula blandit, eget congue justo metus."
#define STR40 "Sed at dolor ipsum. Curabitur cras amet."
__global__ void
splitMessage(__ockl_as_stream_t *stream)
{
const char *str27 = STR27;
const char *str64 = STR64;
const char *str40 = STR40;
const int numStr = 3;
const char *strArray[] = {str27, str64, str40};
int strLengths[] = {27, 64, 40};
const unsigned int tid = blockDim.x * blockIdx.x + threadIdx.x;
int service = tid % 3;
int first = tid % 3;
int second = (tid + 1) % 3;
int third = (tid + 2) % 3;
uint64_t connection_id;
__hip_as_write_block(stream, service, &connection_id,
(unsigned const char *)strArray[first],
strLengths[first], __OCKL_AS_CONNECTION_BEGIN);
__hip_as_write_block(stream, service, &connection_id,
(unsigned const char *)strArray[second],
strLengths[second], 0);
__hip_as_write_block(stream, service, &connection_id,
(unsigned const char *)strArray[third],
strLengths[third], __OCKL_AS_CONNECTION_END);
}
bool
checkSplitMessage(__ockl_as_stream_t *stream)
{
typedef std::unordered_map<uint64_t, std::string> stream_buffer_map_t;
stream_buffer_map_t buffers;
std::unordered_map<std::string, int> strRecd;
static const int numExpected = 3;
const char *strExpected[numExpected] = {STR27 STR64 STR40,
STR64 STR40 STR27,
STR40 STR27 STR64};
for (unsigned long read_index = 0; read_index != stream->write_index;
++read_index) {
__ockl_as_packet_t *packet = stream->base_address + read_index;
uint header = packet->header;
if (get_packet_type(header) != __OCKL_AS_PACKET_READY)
return false;
uint bytes = get_packet_bytes(header);
unsigned char flags = get_packet_flags(header);
unsigned long connection_id = packet->connection_id;
unsigned char *payload = packet->payload;
uint8_t service = get_packet_service(header);
if ((flags & __OCKL_AS_CONNECTION_BEGIN) !=
(buffers.count(connection_id) == 0))
return false;
std::string &buf = buffers[connection_id];
buf.insert(buf.end(), payload, payload + bytes);
if (flags & __OCKL_AS_CONNECTION_END) {
if (buf != strExpected[service])
return false;
strRecd[buf] += 1;
buffers.erase(connection_id);
}
}
int expected_counts[numExpected];
for (int ii = 0; ii != numExpected; ++ii) {
expected_counts[ii] = NUM_THREADS / numExpected;
if (ii < (NUM_THREADS % numExpected)) {
++expected_counts[ii];
}
}
if (strRecd.size() != numExpected)
return false;
for (int ii = 0; ii != numExpected; ++ii) {
std::string mystr(strExpected[ii]);
if (strRecd[mystr] != expected_counts[ii])
return false;
}
return true;
}
bool
ocklAsSplitMessage()
{
bool success = true;
unsigned int numPackets = NUM_PACKETS_LARGE;
unsigned int bufferSize =
sizeof(__ockl_as_stream_t) + numPackets * __OCKL_AS_PACKET_SIZE;
void *buffer;
HIPCHECK(hipHostMalloc(&buffer, bufferSize));
__ockl_as_stream_t *stream = createStream(buffer, bufferSize, numPackets);
hipLaunchKernelGGL(splitMessage, dim3(NUM_BLOCKS), dim3(THREADS_PER_BLOCK),
0, 0, stream);
HIPCHECK(hipDeviceSynchronize());
if (!checkSplitMessage(stream)) {
test_failed(__func__);
success = false;
}
HIPCHECK(hipHostFree(buffer));
return success;
}
#define TESTNAME "hipAsynchronousStreams"
int
main(int argc, char **argv)
{
bool success = true;
success &= ocklAsSinglePacketSingleProducer();
success &= ocklAsMultipleProducers();
success &= ocklAsDropPackets();
success &= ocklAsMixedProducers();
success &= ocklAsSplitMessage();
hipDeviceReset();
if (success) {
test_passed(TESTNAME);
return 0;
}
failed(TESTNAME);
}