From 086387f723cfe9a826ab0a20aa7bb0e023e299d8 Mon Sep 17 00:00:00 2001 From: "Rabbani, Golam" Date: Tue, 12 Sep 2023 09:14:49 -0700 Subject: [PATCH] convert to SYCL version --- CMakeLists.txt | 82 +++++++++-- LICENSE | 24 ---- LICENSE.md | 8 ++ README.md | 111 ++++++--------- screenshot.png | Bin 147016 -> 0 bytes src/acas.h | 66 +++++++++ src/linearprobing.cpp | 313 ++++++++++++++++++++++++++++++++++++++++++ src/linearprobing.cu | 268 ------------------------------------ src/linearprobing.h | 54 ++++++-- src/main.cpp | 232 ++++++++++++++++++++++++------- src/test.cpp | 19 ++- 11 files changed, 743 insertions(+), 434 deletions(-) delete mode 100644 LICENSE create mode 100644 LICENSE.md delete mode 100644 screenshot.png create mode 100644 src/acas.h create mode 100644 src/linearprobing.cpp delete mode 100644 src/linearprobing.cu diff --git a/CMakeLists.txt b/CMakeLists.txt index c260e98..6b7dd8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,19 +1,79 @@ -cmake_minimum_required(VERSION 3.8 FATAL_ERROR) + # Modifications Copyright (C) 2023 Intel Corporation + # + # This Program is subject to the terms of The Unlicense.​ + # If a copy of the license was not distributed with this file, ​ + # you can obtain one at https://spdx.org/licenses/Unlicense.html​ + #​ + # + # SPDX-License-Identifier: Unlicense + # -project(SimpleConcurrentGPUHashTable LANGUAGES CXX CUDA) +cmake_minimum_required(VERSION 3.10) -# put predefined cmake projects in their own solution folder -set_property(GLOBAL PROPERTY USE_FOLDERS ON) +project(hashtable_sycl LANGUAGES CXX) -string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_35,code=sm_35") +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) -set(SOURCE_FILES src/main.cpp src/test.cpp src/linearprobing.h src/linearprobing.cu) +option(GPU_AOT "Build AOT for Intel GPU" OFF) +option(USE_NVIDIA_BACKEND "Build for NVIDIA backend" OFF) +option(USE_AMDHIP_BACKEND "Build for AMD HIP backend" OFF) +option(USE_SM "Build for specific SM" OFF) + +set(INTEL_GPU_CXX_FLAGS " -O2 -fsycl -Wall -Wextra -Wno-unused-parameter ") +set(NVIDIA_GPU_CXX_FLAGS " -O3 -fsycl -Wall -Wextra -Wno-unused-parameter ") +set(AMD_GPU_CXX_FLAGS " -O3 -fsycl -Wall -Wextra -Wno-unused-parameter ") + +set(USE_DEFAULT_FLAGS ON) +if("${CMAKE_CXX_FLAGS}" STREQUAL "") + message(STATUS "Using DEFAULT compilation flags") +else() + message(STATUS "Overriding DEFAULT compilation flags") + set(USE_DEFAULT_FLAGS OFF) +endif() + +# AOT compilation +if(GPU_AOT) + message(STATUS "Enabling INTEL backend") + if(USE_DEFAULT_FLAGS) + set(CMAKE_CXX_FLAGS "${INTEL_GPU_CXX_FLAGS}") # Default flags for Intel backend + endif() + if( (${GPU_AOT} STREQUAL "pvc") OR (${GPU_AOT} STREQUAL "PVC") ) + message(STATUS "Enabling Intel GPU AOT compilation for ${GPU_AOT}") + string(APPEND CMAKE_CXX_FLAGS " -fsycl-targets=spir64_gen -Xs \"-device 0x0bd5 -revision_id 0x2f\" ") + else() + message(STATUS "Using custom AOT compilation flag ${GPU_AOT}") + string(APPEND CMAKE_CXX_FLAGS " ${GPU_AOT} ") + endif() +elseif(USE_NVIDIA_BACKEND) + message(STATUS "Enabling NVIDIA backend") + if(USE_DEFAULT_FLAGS) + set(CMAKE_CXX_FLAGS "${NVIDIA_GPU_CXX_FLAGS}") # Default flags for NV backend + endif() + if(USE_SM) + message("-- Building for SM_${USE_SM} compatibility") + string(APPEND CMAKE_CXX_FLAGS " -fsycl-targets=nvptx64-nvidia-cuda -Xsycl-target-backend --cuda-gpu-arch=sm_${USE_SM} ") + else() + message("-- Building for SM_80 compatibility (DEFAULT)") + string(APPEND CMAKE_CXX_FLAGS " -fsycl-targets=nvptx64-nvidia-cuda -Xsycl-target-backend --cuda-gpu-arch=sm_80 ") + endif() +elseif(USE_AMDHIP_BACKEND) + message(STATUS "Enabling AMD HIP backend for ${USE_AMDHIP_BACKEND} AMD architecture") + if(USE_DEFAULT_FLAGS) + set(CMAKE_CXX_FLAGS "${AMD_GPU_CXX_FLAGS}") # Default flags for AMD backend (gfx90a for MI250) + endif() + string(APPEND CMAKE_CXX_FLAGS " -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=${USE_AMDHIP_BACKEND} ") +endif() + +set(SOURCES + ${CMAKE_SOURCE_DIR}/src/main.cpp + ${CMAKE_SOURCE_DIR}/src/test.cpp + ${CMAKE_SOURCE_DIR}/src/linearprobing.cpp +) include_directories(${CMAKE_SOURCE_DIR}/src) -add_executable(test ${SOURCE_FILES}) +add_executable(${PROJECT_NAME} ${SOURCES}) -# visual studio project should mimic directory structure -# this isn't working for me; I think because -# https://developercommunity.visualstudio.com/content/problem/777578/source-grouptree-no-longer-works.html -source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_FILES}) +target_link_libraries(${PROJECT_NAME} sycl OpenCL stdc++fs) diff --git a/LICENSE b/LICENSE deleted file mode 100644 index fdddb29..0000000 --- a/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -This is free and unencumbered software released into the public domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. - -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. - -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 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. - -For more information, please refer to diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..2977253 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,8 @@ +Modifications Copyright (C) 2023 Intel Corporation + +This Program is subject to the terms of The Unlicense.​ +If a copy of the license was not distributed with this file, ​ +you can obtain one at https://spdx.org/licenses/Unlicense.html​ + + +SPDX-License-Identifier: Unlicense diff --git a/README.md b/README.md index ce2a8c1..46028ed 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,64 @@ -![](screenshot.png) +# hashtable -# About +hashtable implements a simple hash table in GPU (original CUDA source code is from [here](https://github.com/nosferalatu/SimpleGPUHashTable)). -This project shows how to implement a simple GPU hash table. Thanks to the high bandwidth and massive parallelism of -GPU's, the result is a high performance hash table capable of hundreds of millions of operations per second. -The code achieves an average insertion rate of 326 million key/second on my development laptop with an NVIDIA GTX 1060, -measured by inserting 64 million elements. +## SYCL version -[Read my blog post about the code here](http://nosferalatu.com/SimpleGPUHashTable.html) for more information about the -implementation. +- The CUDA code was migrated using Intel DPCT, and then the resulting code was modified to remove the DPCT headers. +- Timing code was later added for performance measurement purpose. +- The same SYCL code runs on Intel GPUs & CPUs as well as NVIDIA (tested on A100 and H100) and AMD (tested on MI100 and MI250) GPUs. -The code implements a lock free hash table using linear probing. Concurrent inserts, deletes, and lookups are supported by -this hash table. The hash table works on 32 bit keys and 32 bit values (although 0xffffffff is reserved for both keys -and values). The load factor of the table is set to 50% in the code, and the table size must be a power of two. +# Build Instructions +- icpx compiler mentioned below is included in oneAPI Base Toolkit available [here](https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit-download.html). +- clang++ compiler mentioned below is available [here](https://github.com/intel/llvm/blob/sycl/sycl/doc/GetStartedGuide.md). +## To build for SYCL -Atomic operations are used to insert key/value pairs into the hash table on multiple GPU threads. It uses CUDA for ease -of development, but could easily be ported to HLSL or GLSL. 64 bit keys and/or values could be supported using 64 bit -atomics. - -Resizing the hash table is not implemented (it's a *simple* hash table!) although this can be achieved by inserting the -contents of a table into another, larger table. - -The code was kept simple for readability. There are many optimizations that can be done, but they muddy the waters. I -wanted to illustrate the basic design of the lock free hash table and how it can be implemented on a GPU. - -# How To Use - -If you build and run the executable, it enters an infinite loop of inserting and deleting random numbers into the -GPU hash table and verifying that the results are correct. The seed used to generate random numbers changes every time -you run the executable, but you can set the seed to a specific value in code if you'd like to reproduce results across -runs. - -This is how you insert a vector of `KeyValue` pairs into the hash table and then retrieve all the `KeyValue` pairs back: - -```cpp - std::vector things_to_insert = { {0,1}, {1,2}, {2,3}, {3,4} }; - - KeyValue* pHashTable = create_hashtable(); - insert_hashtable(pHashTable, things_to_insert.data(), (uint32_t)things_to_insert.size()); - std::vector result = iterate_hashtable(pHashTable); - destroy_hashtable(pHashTable); -``` - -After that runs, the vectors `things_to_insert` and `result` should be the same, but possibly in a different order. - -# Prerequisites - -* CMake -* CUDA - -This has been tested on Windows with Visual Studio Community 2019 on a machine with an NVIDIA GTX 1060. -An easy way to get CMake is to open a Visual Studio command prompt (in Windows, run "x64 Native Tools Command Prompt for -VS 2019"; that will put CMake in your path). - -This should work on other CUDA-supported platforms, but I have not tested this. - -# Cloning +For Intel GPU - +First, source icpx compiler. Then, ``` -git clone https://github.com/nosferalatu/SimpleConcurrentGPUHashTable.git SimpleConcurrentGPUHashTable +mkdir build +cd build +CXX=icpx cmake -DGPU_AOT=pvc .. +make -sj ``` +Note: +- To enable AOT compilation, please use the flag `-DGPU_AOT=pvc` for PVC. -# Generating Build Files - -Run the following commands to generate .sln and .vcxproj's that can be opened in Visual Studio: - +For AMD GPU - +First source clang++ compiler. Then, ``` -cd ConcurrentHashTables -md build +mkdir build cd build -cmake .. +CXX=clang++ cmake -DUSE_AMDHIP_BACKEND=gfx90a .. +make -sj ``` +Note: +- We use the flag `-DUSE_AMDHIP_BACKEND=gfx90a` for MI250. Use the correct value for your GPU. -You can now open `SimpleConcurrentGPUHashTable.sln` in Visual Studio. - -If CMake fails to find CUDA above, then run a CMake generator for 64 bit builds: +For NVIDIA GPU - +First source clang++ compiler. Then, ``` -cmake -G "Visual Studio 16 2019 Win64" .. +mkdir build +cd build +CXX=clang++ cmake -DUSE_NVIDIA_BACKEND=YES -DUSE_SM=80 .. +make -sj ``` +Note: +- We use the flag `-DUSE_SM=80` for A100 or `-DUSE_SM=90` for H100. -# Building +# Run instructions -You can build within Visual Studio, or from the command line with: +After building, to run the workload, cd into the build folder. Then ``` -cmake --build . --config Release +./hashtable_sycl +``` +By default a verification is done and that takes some time. To skip verification: ``` +./hashtable_sycl --no-verify +``` +# Output + +Output gives number of keys per second. diff --git a/screenshot.png b/screenshot.png deleted file mode 100644 index b8c09fdc9f69dea0573304d13c822cbf8687ce37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 147016 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 whOBuyvP}3~bBS{1`oxo3rt_cyI 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 + +namespace acas { + +/// Atomically compare the value at \p addr to the value expected and exchange +/// with the value desired if the value at \p addr is equal to the value expected. +/// Returns the value at the \p addr before the call. +/// \param [in, out] addr Multi_ptr. +/// \param expected The value to compare against the value at \p addr. +/// \param desired The value to assign to \p addr if the value at \p addr is expected. +/// \param success The memory ordering used when comparison succeeds. +/// \param fail The memory ordering used when comparison fails. +/// \returns The value at the \p addr before the call. +template +T atomic_compare_exchange_strong( + sycl::multi_ptr addr, + T expected, + T desired, + sycl::memory_order success = sycl::memory_order::relaxed, + sycl::memory_order fail = sycl::memory_order::relaxed +) { + // sycl::atomic_ref obj(addr); + sycl::atomic_ref obj(addr[0]); + obj.compare_exchange_strong(expected, desired, success, fail); + return expected; +} + +/// Atomically compare the value at \p addr to the value expected and exchange +/// with the value desired if the value at \p addr is equal to the value expected. +/// Returns the value at the \p addr before the call. +/// \param [in] addr The pointer to the data. +/// \param expected The value to compare against the value at \p addr. +/// \param desired The value to assign to \p addr if the value at \p addr is expected. +/// \param success The memory ordering used when comparison succeeds. +/// \param fail The memory ordering used when comparison fails. +/// \returns The value at the \p addr before the call. +template +T atomic_compare_exchange_strong( + T* addr, + T expected, + T desired, + sycl::memory_order success = sycl::memory_order::relaxed, + sycl::memory_order fail = sycl::memory_order::relaxed +) { + return atomic_compare_exchange_strong(sycl::multi_ptr(addr), expected, desired, success, fail); +} + +} // namespace acas diff --git a/src/linearprobing.cpp b/src/linearprobing.cpp new file mode 100644 index 0000000..0642443 --- /dev/null +++ b/src/linearprobing.cpp @@ -0,0 +1,313 @@ +/* Modifications Copyright (C) 2023 Intel Corporation + * + * This Program is subject to the terms of The Unlicense.​ + * If a copy of the license was not distributed with this file, ​ + * you can obtain one at https://spdx.org/licenses/Unlicense.html​ + *​ + * + * SPDX-License-Identifier: Unlicense + */ + +#include "stdio.h" +#include "stdint.h" +#include "vector" + +#define CPP_MODULE "KERNEL" +#include "linearprobing.h" + +#include +#include +#include "acas.h" + +// 32 bit Murmur3 hash +uint32_t hash(uint32_t k) +{ + k ^= k >> 16; + k *= 0x85ebca6b; + k ^= k >> 13; + k *= 0xc2b2ae35; + k ^= k >> 16; + return k & (kHashTableCapacity - 1); +} + +// Create a hash table. For linear probing, this is just an array of KeyValues +KeyValue* create_hashtable(sycl::queue& qht) +{ + KeyValue* hashtable; + + try { + // Allocate memory + hashtable = sycl::malloc_device(kHashTableCapacity, qht); + + // Initialize hash table to empty + static_assert(kEmpty == 0xFFFFFFFF, "memset expected kEmpty=0xFFFFFFFF"); + qht.memset(hashtable, 0xFF, sizeof(KeyValue) * kHashTableCapacity); + qht.wait(); + } catch (std::exception const& e) { + LOG_ERROR("Exception caught, \'" << e.what() << "\'"); + } catch (...) { + LOG_ERROR("Unknown exception caught, bailing..."); + } + + return hashtable; +} + +// Insert the key/values in kvs into the hashtable +void gpu_hashtable_insert( + KeyValue* hashtable, + const KeyValue* kvs, + unsigned int numkvs, + sycl::nd_item<1> item) +{ + unsigned int tid = item.get_global_id(0); + if (tid < numkvs) { + uint32_t key = kvs[tid].key; + uint32_t value = kvs[tid].value; + uint32_t slot = hash(key); + + while (true) { + uint32_t prev = acas::atomic_compare_exchange_strong(&hashtable[slot].key, kEmpty, key); + if (prev == kEmpty || prev == key) { + hashtable[slot].value = value; + return; + } + + slot = (slot + 1) & (kHashTableCapacity - 1); + } + } +} + +void insert_hashtable( + KeyValue* pHashTable, // hashtable + const KeyValue* kvs, // starting position for this batch of key-value pairs + uint32_t num_kvs, // number of key-value pairs in this batch + sycl::queue& qht) +{ + try { + // Copy this batch of key-value pairs to the device + KeyValue* device_kvs; + device_kvs = sycl::malloc_device(num_kvs, qht); + auto e1 = qht.memcpy(device_kvs, kvs, sizeof(KeyValue) * num_kvs); + + int threadblocksize = 256; // perf does not seem to vary w/ thread block size (for all kernels in hashtable) + + // Create events for GPU timing + qht.parallel_for( + sycl::nd_range<1>(num_kvs, threadblocksize), std::move(e1), + [=](sycl::nd_item<1> item) { + + gpu_hashtable_insert( + pHashTable, + device_kvs, + (uint32_t)num_kvs, + item); + } + ); + qht.wait(); + + sycl::free(device_kvs, qht); + } catch (std::exception const& e) { + LOG_ERROR("Exception caught, \'" << e.what() << "\'"); + } catch (...) { + LOG_ERROR("Unknown exception caught, bailing..."); + } +} + +// Lookup keys in the hashtable, and return the values +void gpu_hashtable_lookup( + KeyValue* hashtable, + KeyValue* kvs, + unsigned int numkvs, + sycl::nd_item<1> item) +{ + unsigned int tid = item.get_global_id(0); + if (tid < numkvs) { + uint32_t key = kvs[tid].key; + uint32_t slot = hash(key); + + while (true) { + if (hashtable[slot].key == key) { + kvs[tid].value = hashtable[slot].value; + return; + } + if (hashtable[slot].key == kEmpty) { + kvs[tid].value = kEmpty; + return; + } + slot = (slot + 1) & (kHashTableCapacity - 1); + } + } +} + +void lookup_hashtable( + KeyValue* pHashTable, + KeyValue* kvs, + uint32_t num_kvs, + sycl::queue& qht) +{ + try { + // Copy this batch of key-value pairs to the device + KeyValue* device_kvs; + device_kvs = sycl::malloc_device(num_kvs, qht); + auto e1 = qht.memcpy(device_kvs, kvs, sizeof(KeyValue) * num_kvs); + + int threadblocksize = 256; + + qht.parallel_for( + sycl::nd_range<1>(num_kvs, threadblocksize), std::move(e1), + [=](sycl::nd_item<1> item) { + + gpu_hashtable_lookup( + pHashTable, + device_kvs, + (uint32_t)num_kvs, + item); + } + ); + qht.wait(); + + sycl::free(device_kvs, qht); + } catch (std::exception const& e) { + LOG_ERROR("Exception caught, \'" << e.what() << "\'"); + } catch (...) { + LOG_ERROR("Unknown exception caught, bailing..."); + } +} + +// Delete each key in kvs from the hash table, if the key exists +// A deleted key is left in the hash table, but its value is set to kEmpty +// Deleted keys are not reused; once a key is assigned a slot, it never moves +void gpu_hashtable_delete( + KeyValue* hashtable, + const KeyValue* kvs, + unsigned int numkvs, + sycl::nd_item<1> item) +{ + unsigned int tid = item.get_global_id(0); + if (tid < numkvs) { + uint32_t key = kvs[tid].key; + uint32_t slot = hash(key); + + while (true) { + if (hashtable[slot].key == key) { + hashtable[slot].value = kEmpty; + return; + } + if (hashtable[slot].key == kEmpty) { + return; + } + slot = (slot + 1) & (kHashTableCapacity - 1); + } + } +} + +void delete_hashtable( + KeyValue* pHashTable, + const KeyValue* kvs, + uint32_t num_kvs, + sycl::queue& qht) +{ + try { + // Copy the keyvalues to the GPU + KeyValue* device_kvs; + device_kvs = sycl::malloc_device(num_kvs, qht); + auto e1 = qht.memcpy(device_kvs, kvs, sizeof(KeyValue) * num_kvs); + + int threadblocksize = 256; + + qht.parallel_for( + sycl::nd_range<1>(num_kvs, threadblocksize), std::move(e1), + [=](sycl::nd_item<1> item) { + + gpu_hashtable_delete( + pHashTable, + device_kvs, + (uint32_t)num_kvs, + item) ; + } + ); + qht.wait(); + + sycl::free(device_kvs, qht); + } catch (std::exception const& e) { + LOG_ERROR("Exception caught, \'" << e.what() << "\'"); + } catch (...) { + LOG_ERROR("Unknown exception caught, bailing..."); + } +} + +// Iterate over every item in the hashtable; return non-empty key/values +void gpu_iterate_hashtable( + KeyValue* pHashTable, + KeyValue* kvs, + uint32_t* kvs_size, + sycl::nd_item<1> item) +{ + unsigned int tid = item.get_global_id(0); + if (tid < kHashTableCapacity) { + if (pHashTable[tid].key != kEmpty) { + uint32_t value = pHashTable[tid].value; + if (value != kEmpty) { + // uint32_t size = sycl::atomic(sycl::global_ptr(kvs_size)).fetch_add(1); + uint32_t size = sycl::atomic_ref(kvs_size[0]).fetch_add(1); + kvs[size] = pHashTable[tid]; + } + } + } +} + +std::vector iterate_hashtable( + KeyValue* pHashTable, + sycl::queue& qht) +{ + std::vector kvs; + + try { + uint32_t* device_num_kvs; + KeyValue* device_kvs; + device_num_kvs = sycl::malloc_device(1, qht); + device_kvs = sycl::malloc_device(kNumKeyValues, qht); + + auto e1 = qht.memset(device_num_kvs, 0, sizeof(uint32_t)); + + int threadblocksize = 256; + + auto e2 = qht.parallel_for( + sycl::nd_range<1>(kHashTableCapacity, threadblocksize), std::move(e1), + [=](sycl::nd_item<1> item) { + + gpu_iterate_hashtable( + pHashTable, + device_kvs, + device_num_kvs, + item); + } + ); + + uint32_t num_kvs; + qht.memcpy(&num_kvs, device_num_kvs, sizeof(uint32_t), std::move(e2)); + qht.wait(); + + kvs.resize(num_kvs); + + qht.memcpy(kvs.data(), device_kvs, sizeof(KeyValue) * num_kvs); + qht.wait(); + + sycl::free(device_kvs, qht); + sycl::free(device_num_kvs, qht); + } catch (std::exception const& e) { + LOG_ERROR("Exception caught, \'" << e.what() << "\'"); + } catch (...) { + LOG_ERROR("Unknown exception caught, bailing..."); + } + + return kvs; +} + +// Free the memory of the hashtable +void destroy_hashtable( + KeyValue* pHashTable, + sycl::queue& qht) +{ + sycl::free(pHashTable, qht); +} diff --git a/src/linearprobing.cu b/src/linearprobing.cu deleted file mode 100644 index ac75d9d..0000000 --- a/src/linearprobing.cu +++ /dev/null @@ -1,268 +0,0 @@ -#include "stdio.h" -#include "stdint.h" -#include "vector" -#include "linearprobing.h" - -// 32 bit Murmur3 hash -__device__ uint32_t hash(uint32_t k) -{ - k ^= k >> 16; - k *= 0x85ebca6b; - k ^= k >> 13; - k *= 0xc2b2ae35; - k ^= k >> 16; - return k & (kHashTableCapacity-1); -} - -// Create a hash table. For linear probing, this is just an array of KeyValues -KeyValue* create_hashtable() -{ - // Allocate memory - KeyValue* hashtable; - cudaMalloc(&hashtable, sizeof(KeyValue) * kHashTableCapacity); - - // Initialize hash table to empty - static_assert(kEmpty == 0xffffffff, "memset expected kEmpty=0xffffffff"); - cudaMemset(hashtable, 0xff, sizeof(KeyValue) * kHashTableCapacity); - - return hashtable; -} - -// Insert the key/values in kvs into the hashtable -__global__ void gpu_hashtable_insert(KeyValue* hashtable, const KeyValue* kvs, unsigned int numkvs) -{ - unsigned int threadid = blockIdx.x*blockDim.x + threadIdx.x; - if (threadid < numkvs) - { - uint32_t key = kvs[threadid].key; - uint32_t value = kvs[threadid].value; - uint32_t slot = hash(key); - - while (true) - { - uint32_t prev = atomicCAS(&hashtable[slot].key, kEmpty, key); - if (prev == kEmpty || prev == key) - { - hashtable[slot].value = value; - return; - } - - slot = (slot + 1) & (kHashTableCapacity-1); - } - } -} - -void insert_hashtable(KeyValue* pHashTable, const KeyValue* kvs, uint32_t num_kvs) -{ - // Copy the keyvalues to the GPU - KeyValue* device_kvs; - cudaMalloc(&device_kvs, sizeof(KeyValue) * num_kvs); - cudaMemcpy(device_kvs, kvs, sizeof(KeyValue) * num_kvs, cudaMemcpyHostToDevice); - - // Have CUDA calculate the thread block size - int mingridsize; - int threadblocksize; - cudaOccupancyMaxPotentialBlockSize(&mingridsize, &threadblocksize, gpu_hashtable_insert, 0, 0); - - // Create events for GPU timing - cudaEvent_t start, stop; - cudaEventCreate(&start); - cudaEventCreate(&stop); - - cudaEventRecord(start); - - // Insert all the keys into the hash table - int gridsize = ((uint32_t)num_kvs + threadblocksize - 1) / threadblocksize; - gpu_hashtable_insert<<>>(pHashTable, device_kvs, (uint32_t)num_kvs); - - cudaEventRecord(stop); - - cudaEventSynchronize(stop); - - float milliseconds = 0; - cudaEventElapsedTime(&milliseconds, start, stop); - float seconds = milliseconds / 1000.0f; - printf(" GPU inserted %d items in %f ms (%f million keys/second)\n", - num_kvs, milliseconds, num_kvs / (double)seconds / 1000000.0f); - - cudaFree(device_kvs); -} - -// Lookup keys in the hashtable, and return the values -__global__ void gpu_hashtable_lookup(KeyValue* hashtable, KeyValue* kvs, unsigned int numkvs) -{ - unsigned int threadid = blockIdx.x * blockDim.x + threadIdx.x; - if (threadid < numkvs) - { - uint32_t key = kvs[threadid].key; - uint32_t slot = hash(key); - - while (true) - { - if (hashtable[slot].key == key) - { - kvs[threadid].value = hashtable[slot].value; - return; - } - if (hashtable[slot].key == kEmpty) - { - kvs[threadid].value = kEmpty; - return; - } - slot = (slot + 1) & (kHashTableCapacity - 1); - } - } -} - -void lookup_hashtable(KeyValue* pHashTable, KeyValue* kvs, uint32_t num_kvs) -{ - // Copy the keyvalues to the GPU - KeyValue* device_kvs; - cudaMalloc(&device_kvs, sizeof(KeyValue) * num_kvs); - cudaMemcpy(device_kvs, kvs, sizeof(KeyValue) * num_kvs, cudaMemcpyHostToDevice); - - // Have CUDA calculate the thread block size - int mingridsize; - int threadblocksize; - cudaOccupancyMaxPotentialBlockSize(&mingridsize, &threadblocksize, gpu_hashtable_insert, 0, 0); - - // Create events for GPU timing - cudaEvent_t start, stop; - cudaEventCreate(&start); - cudaEventCreate(&stop); - - cudaEventRecord(start); - - // Insert all the keys into the hash table - int gridsize = ((uint32_t)num_kvs + threadblocksize - 1) / threadblocksize; - gpu_hashtable_lookup << > > (pHashTable, device_kvs, (uint32_t)num_kvs); - - cudaEventRecord(stop); - - cudaEventSynchronize(stop); - - float milliseconds = 0; - cudaEventElapsedTime(&milliseconds, start, stop); - float seconds = milliseconds / 1000.0f; - printf(" GPU lookup %d items in %f ms (%f million keys/second)\n", - num_kvs, milliseconds, num_kvs / (double)seconds / 1000000.0f); - - cudaFree(device_kvs); -} - -// Delete each key in kvs from the hash table, if the key exists -// A deleted key is left in the hash table, but its value is set to kEmpty -// Deleted keys are not reused; once a key is assigned a slot, it never moves -__global__ void gpu_hashtable_delete(KeyValue* hashtable, const KeyValue* kvs, unsigned int numkvs) -{ - unsigned int threadid = blockIdx.x * blockDim.x + threadIdx.x; - if (threadid < numkvs) - { - uint32_t key = kvs[threadid].key; - uint32_t slot = hash(key); - - while (true) - { - if (hashtable[slot].key == key) - { - hashtable[slot].value = kEmpty; - return; - } - if (hashtable[slot].key == kEmpty) - { - return; - } - slot = (slot + 1) & (kHashTableCapacity - 1); - } - } -} - -void delete_hashtable(KeyValue* pHashTable, const KeyValue* kvs, uint32_t num_kvs) -{ - // Copy the keyvalues to the GPU - KeyValue* device_kvs; - cudaMalloc(&device_kvs, sizeof(KeyValue) * num_kvs); - cudaMemcpy(device_kvs, kvs, sizeof(KeyValue) * num_kvs, cudaMemcpyHostToDevice); - - // Have CUDA calculate the thread block size - int mingridsize; - int threadblocksize; - cudaOccupancyMaxPotentialBlockSize(&mingridsize, &threadblocksize, gpu_hashtable_insert, 0, 0); - - // Create events for GPU timing - cudaEvent_t start, stop; - cudaEventCreate(&start); - cudaEventCreate(&stop); - - cudaEventRecord(start); - - // Insert all the keys into the hash table - int gridsize = ((uint32_t)num_kvs + threadblocksize - 1) / threadblocksize; - gpu_hashtable_delete<< > > (pHashTable, device_kvs, (uint32_t)num_kvs); - - cudaEventRecord(stop); - - cudaEventSynchronize(stop); - - float milliseconds = 0; - cudaEventElapsedTime(&milliseconds, start, stop); - float seconds = milliseconds / 1000.0f; - printf(" GPU delete %d items in %f ms (%f million keys/second)\n", - num_kvs, milliseconds, num_kvs / (double)seconds / 1000000.0f); - - cudaFree(device_kvs); -} - -// Iterate over every item in the hashtable; return non-empty key/values -__global__ void gpu_iterate_hashtable(KeyValue* pHashTable, KeyValue* kvs, uint32_t* kvs_size) -{ - unsigned int threadid = blockIdx.x * blockDim.x + threadIdx.x; - if (threadid < kHashTableCapacity) - { - if (pHashTable[threadid].key != kEmpty) - { - uint32_t value = pHashTable[threadid].value; - if (value != kEmpty) - { - uint32_t size = atomicAdd(kvs_size, 1); - kvs[size] = pHashTable[threadid]; - } - } - } -} - -std::vector iterate_hashtable(KeyValue* pHashTable) -{ - uint32_t* device_num_kvs; - cudaMalloc(&device_num_kvs, sizeof(uint32_t)); - cudaMemset(device_num_kvs, 0, sizeof(uint32_t)); - - KeyValue* device_kvs; - cudaMalloc(&device_kvs, sizeof(KeyValue) * kNumKeyValues); - - int mingridsize; - int threadblocksize; - cudaOccupancyMaxPotentialBlockSize(&mingridsize, &threadblocksize, gpu_iterate_hashtable, 0, 0); - - int gridsize = (kHashTableCapacity + threadblocksize - 1) / threadblocksize; - gpu_iterate_hashtable<<>>(pHashTable, device_kvs, device_num_kvs); - - uint32_t num_kvs; - cudaMemcpy(&num_kvs, device_num_kvs, sizeof(uint32_t), cudaMemcpyDeviceToHost); - - std::vector kvs; - kvs.resize(num_kvs); - - cudaMemcpy(kvs.data(), device_kvs, sizeof(KeyValue) * num_kvs, cudaMemcpyDeviceToHost); - - cudaFree(device_kvs); - cudaFree(device_num_kvs); - - return kvs; -} - -// Free the memory of the hashtable -void destroy_hashtable(KeyValue* pHashTable) -{ - cudaFree(pHashTable); -} diff --git a/src/linearprobing.h b/src/linearprobing.h index 6487e8b..5cadba3 100644 --- a/src/linearprobing.h +++ b/src/linearprobing.h @@ -1,25 +1,63 @@ +/* Modifications Copyright (C) 2023 Intel Corporation + * + * This Program is subject to the terms of The Unlicense.​ + * If a copy of the license was not distributed with this file, ​ + * you can obtain one at https://spdx.org/licenses/Unlicense.html​ + *​ + * + * SPDX-License-Identifier: Unlicense + */ + #pragma once +#include +#include +#include + +#ifndef CPP_MODULE +#define CPP_MODULE "UNKN" +#endif + struct KeyValue { uint32_t key; uint32_t value; }; -const uint32_t kHashTableCapacity = 128 * 1024 * 1024; +const uint32_t kHashTableCapacity = 256 * 1024 * 1024; const uint32_t kNumKeyValues = kHashTableCapacity / 2; -const uint32_t kEmpty = 0xffffffff; +const uint32_t kEmpty = 0xFFFFFFFF; + +const uint32_t NUM_LOOPS = 1; -KeyValue* create_hashtable(); +KeyValue* create_hashtable(sycl::queue& qht); -void insert_hashtable(KeyValue* hashtable, const KeyValue* kvs, uint32_t num_kvs); +void insert_hashtable(KeyValue* hashtable, const KeyValue* kvs, uint32_t num_kvs, sycl::queue& qht); +void lookup_hashtable(KeyValue* hashtable, KeyValue* kvs, uint32_t num_kvs, sycl::queue& qht); +void delete_hashtable(KeyValue* hashtable, const KeyValue* kvs, uint32_t num_kvs, sycl::queue& qht); -void lookup_hashtable(KeyValue* hashtable, KeyValue* kvs, uint32_t num_kvs); +std::vector iterate_hashtable(KeyValue* hashtable, sycl::queue& qht); -void delete_hashtable(KeyValue* hashtable, const KeyValue* kvs, uint32_t num_kvs); +void destroy_hashtable(KeyValue* hashtable, sycl::queue& qht); -std::vector iterate_hashtable(KeyValue* hashtable); +#define checkCUDA(expression) \ +{ \ + cudaError_t const status(expression); \ + if (status != cudaSuccess) { \ + std::stringstream sErrorMessage; \ + sErrorMessage << "Error on line " << __LINE__ << ": " \ + << cudaGetErrorString(status) << "\n"; \ + throw std::runtime_error(sErrorMessage.str()); \ + std::exit(EXIT_FAILURE); \ + } \ +} -void destroy_hashtable(KeyValue* hashtable); +#define LOG_ERROR(msg) \ +{ \ + std::stringstream sErrorMessage; \ + sErrorMessage << CPP_MODULE << " ERROR(" << __LINE__<< "): " << msg << "\n"; \ + std::cerr << sErrorMessage.str(); \ + throw std::runtime_error(sErrorMessage.str()); \ +} diff --git a/src/main.cpp b/src/main.cpp index 9b15dc2..c7f8e32 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,3 +1,13 @@ +/* Modifications Copyright (C) 2023 Intel Corporation + * + * This Program is subject to the terms of The Unlicense.​ + * If a copy of the license was not distributed with this file, ​ + * you can obtain one at https://spdx.org/licenses/Unlicense.html​ + *​ + * + * SPDX-License-Identifier: Unlicense + */ + #include "algorithm" #include "random" #include "stdint.h" @@ -6,11 +16,48 @@ #include "unordered_set" #include "vector" #include "chrono" +#include + +// #define DEBUG_TIME +#define CPP_MODULE "MAIN" #include "linearprobing.h" +#define TIMER_START() time_start = std::chrono::steady_clock::now(); +#define TIMER_END() \ + time_end = std::chrono::steady_clock::now(); \ + time_total = std::chrono::duration(time_end - time_start).count(); +#define TIMER_PRINT(name) std::cout << name <<": " << time_total / 1e3 << " s\n"; + +#ifdef DEBUG_TIME +#define START_TIMER() start_time = std::chrono::steady_clock::now(); +#define STOP_TIMER() \ + stop_time = std::chrono::steady_clock::now(); \ + duration = std::chrono::duration(stop_time - start_time).count(); \ + tot_time += duration; +#define PRINT_TIMER(name) std::cout <; + +Time start_timer() +{ + return std::chrono::steady_clock::now(); +} + +double get_elapsed_time(Time start) +{ + Time end = std::chrono::steady_clock::now(); + + std::chrono::duration d = end - start; + std::chrono::microseconds us = std::chrono::duration_cast(d); + return us.count() / 1000.0f; +} + // Create random keys/values in the range [0, kEmpty) // kEmpty is used to indicate an empty slot -std::vector generate_random_keyvalues(std::mt19937& rnd, uint32_t numkvs) +std::vector generate_random_keyvalues( + std::mt19937& rnd, + uint32_t numkvs) { std::uniform_int_distribution dis(0, kEmpty - 1); @@ -28,7 +75,10 @@ std::vector generate_random_keyvalues(std::mt19937& rnd, uint32_t numk } // return numshuffledkvs random items from kvs -std::vector shuffle_keyvalues(std::mt19937& rnd, std::vector kvs, uint32_t numshuffledkvs) +std::vector shuffle_keyvalues( + std::mt19937& rnd, + std::vector kvs, + uint32_t numshuffledkvs) { std::shuffle(kvs.begin(), kvs.end(), rnd); @@ -40,23 +90,9 @@ std::vector shuffle_keyvalues(std::mt19937& rnd, std::vector return shuffled_kvs; } -using Time = std::chrono::time_point; - -Time start_timer() -{ - return std::chrono::high_resolution_clock::now(); -} - -double get_elapsed_time(Time start) -{ - Time end = std::chrono::high_resolution_clock::now(); - - std::chrono::duration d = end - start; - std::chrono::microseconds us = std::chrono::duration_cast(d); - return us.count() / 1000.0f; -} - -void test_unordered_map(std::vector insert_kvs, std::vector delete_kvs) +void test_unordered_map( + std::vector insert_kvs, + std::vector delete_kvs) { Time timer = start_timer(); @@ -78,69 +114,161 @@ void test_unordered_map(std::vector insert_kvs, std::vector double milliseconds = get_elapsed_time(timer); double seconds = milliseconds / 1000.0f; - printf("Total time for std::unordered_map: %f ms (%f million keys/second)\n", + printf("Total time for std::unordered_map: %f ms (%f Mkeys/second)\n", milliseconds, kNumKeyValues / seconds / 1000000.0f); } -void test_correctness(std::vector, std::vector, std::vector); +void test_correctness( + std::vector, + std::vector, + std::vector); -int main() +int main(int argc, char* argv[]) { + std::chrono::steady_clock::time_point time_start; + std::chrono::steady_clock::time_point time_end; + double time_total = 0.0; + + try { + // To recreate the same random numbers across runs of the program, set seed to a specific // number instead of a number from random_device std::random_device rd; uint32_t seed = rd(); std::mt19937 rnd(seed); // mersenne_twister_engine - printf("Random number generator seed = %u\n", seed); + // printf("Random number generator seed = %u\n", seed); - while (true) - { - printf("Initializing keyvalue pairs with random numbers...\n"); + // double seconds; + // for (uint32_t n = 0; n < NUM_LOOPS; ++n) { + // printf("Initializing keyvalue pairs with random numbers...\n"); + +#ifdef DEBUG_TIME + std::chrono::steady_clock::time_point start_time; + std::chrono::steady_clock::time_point stop_time; + double duration = 0.0; + double tot_time = 0.0; + START_TIMER(); +#endif std::vector insert_kvs = generate_random_keyvalues(rnd, kNumKeyValues); + std::vector lookup_kvs = shuffle_keyvalues(rnd, insert_kvs, kNumKeyValues / 2); std::vector delete_kvs = shuffle_keyvalues(rnd, insert_kvs, kNumKeyValues / 2); - // Begin test - printf("Testing insertion/deletion of %d/%d elements into GPU hash table...\n", - (uint32_t)insert_kvs.size(), (uint32_t)delete_kvs.size()); - - Time timer = start_timer(); - - KeyValue* pHashTable = create_hashtable(); - - // Insert items into the hash table +#ifdef DEBUG_TIME +STOP_TIMER(); +PRINT_TIMER("generate_hashtable "); +#endif + + TIMER_START() + +#ifdef DEBUG_TIME +START_TIMER(); +#endif + sycl::queue qht; +#ifdef DEBUG_TIME +STOP_TIMER(); +PRINT_TIMER("init "); + +START_TIMER(); +#endif + // Allocates device memory for the hashtable and + // fills every byte with 0xFF (so each key (and value) is set to 0xFFFFFFFF) + KeyValue* pHashTable = create_hashtable(qht); +#ifdef DEBUG_TIME +STOP_TIMER(); +PRINT_TIMER("create_hashtable "); + +START_TIMER(); +#endif + // Insert items into the hash table in batches of num_inserts_per_batch const uint32_t num_insert_batches = 16; uint32_t num_inserts_per_batch = (uint32_t)insert_kvs.size() / num_insert_batches; - for (uint32_t i = 0; i < num_insert_batches; i++) - { - insert_hashtable(pHashTable, insert_kvs.data() + i * num_inserts_per_batch, num_inserts_per_batch); + for (uint32_t i = 0; i < num_insert_batches; i++) { + + insert_hashtable( + pHashTable, + insert_kvs.data() + i * num_inserts_per_batch, + num_inserts_per_batch, + qht); + } +#ifdef DEBUG_TIME +STOP_TIMER(); +PRINT_TIMER("insert_hashtable "); + +START_TIMER(); +#endif + // Look up items from the hash table in batches of num_lookups_per_batch + const uint32_t num_lookup_batches = 8; + uint32_t num_lookups_per_batch = (uint32_t)lookup_kvs.size() / num_lookup_batches; + for (uint32_t i = 0; i < num_lookup_batches; i++) { + + lookup_hashtable( + pHashTable, + lookup_kvs.data() + i * num_lookups_per_batch, + num_lookups_per_batch, + qht); } +#ifdef DEBUG_TIME +STOP_TIMER(); +PRINT_TIMER("lookup_hashtable "); - // Delete items from the hash table +START_TIMER(); +#endif + // Delete items from the hash table in batches of num_deletes_per_batch const uint32_t num_delete_batches = 8; uint32_t num_deletes_per_batch = (uint32_t)delete_kvs.size() / num_delete_batches; - for (uint32_t i = 0; i < num_delete_batches; i++) - { - delete_hashtable(pHashTable, delete_kvs.data() + i * num_deletes_per_batch, num_deletes_per_batch); + for (uint32_t i = 0; i < num_delete_batches; i++) { + + delete_hashtable( + pHashTable, + delete_kvs.data() + i * num_deletes_per_batch, + num_deletes_per_batch, + qht); } +#ifdef DEBUG_TIME +STOP_TIMER(); +PRINT_TIMER("delete_hashtable "); +START_TIMER(); +#endif // Get all the key-values from the hash table - std::vector kvs = iterate_hashtable(pHashTable); - - destroy_hashtable(pHashTable); + std::vector kvs = iterate_hashtable(pHashTable, qht); +#ifdef DEBUG_TIME +STOP_TIMER(); +PRINT_TIMER("iterate_hashtable "); +#endif +// std::cout << "tot_time: " << tot_time << " ms" << std::endl; // Summarize results - double milliseconds = get_elapsed_time(timer); - double seconds = milliseconds / 1000.0f; - printf("Total time (including memory copies, readback, etc): %f ms (%f million keys/second)\n", milliseconds, - kNumKeyValues / seconds / 1000000.0f); + // double milliseconds = get_elapsed_time(timer); + // seconds = milliseconds / 1000.0f; - test_unordered_map(insert_kvs, delete_kvs); + destroy_hashtable(pHashTable, qht); - test_correctness(insert_kvs, delete_kvs, kvs); + TIMER_END() + TIMER_PRINT("hashtable - total time for whole calculation") + printf("%f million keys/second\n", kNumKeyValues / (time_total / 1000.0f) / 1000000.0f); - printf("Success\n"); + bool verify = true; + if (argc > 1 && strcmp(argv[1], "--no-verify") == 0) { + verify = false; + } + if (verify) { + test_unordered_map(insert_kvs, delete_kvs); + test_correctness(insert_kvs, delete_kvs, std::move(kvs)); + printf("Success\n"); + } + // } + // printf("Total time: %f s\n", seconds); + // printf("%f million keys/second\n", kNumKeyValues / seconds / 1000000.0f); + + } catch (std::exception const& e) { + std::cout << "Exception caught, \'" << e.what() << "\'"; + return 1; + } catch (...) { + std::cout << "Unknown exception caught, bailing..."; + return 2; } return 0; diff --git a/src/test.cpp b/src/test.cpp index ad454a4..4b8aef4 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -1,3 +1,13 @@ +/* Modifications Copyright (C) 2023 Intel Corporation + * + * This Program is subject to the terms of The Unlicense.​ + * If a copy of the license was not distributed with this file, ​ + * you can obtain one at https://spdx.org/licenses/Unlicense.html​ + *​ + * + * SPDX-License-Identifier: Unlicense + */ + #include "stdio.h" #include "stdint.h" #include "unordered_set" @@ -7,7 +17,10 @@ #include "random" #include "linearprobing.h" -void test_correctness(std::vector insert_kvs, std::vector delete_kvs, std::vector kvs) +void test_correctness( + std::vector insert_kvs, + std::vector delete_kvs, + std::vector kvs) { printf("Testing that there are no duplicate keys...\n"); std::unordered_set unique_keys; @@ -27,7 +40,7 @@ void test_correctness(std::vector insert_kvs, std::vector de printf("Building unordered_map from original list...\n"); std::unordered_map> all_kvs_map; - for (int i = 0; i < insert_kvs.size(); i++) + for (uint32_t i = 0; i < insert_kvs.size(); i++) { if (i % 10000000 == 0) printf(" Inserting %d/%d\n", i, (uint32_t)insert_kvs.size()); @@ -43,7 +56,7 @@ void test_correctness(std::vector insert_kvs, std::vector de } } - for (int i = 0; i < delete_kvs.size(); i++) + for (uint32_t i = 0; i < delete_kvs.size(); i++) { if (i % 10000000 == 0) printf(" Deleting %d/%d\n", i, (uint32_t)delete_kvs.size());