Files
2026-07-13 13:35:51 +08:00

123 lines
3.8 KiB
C++

/*
* Copyright (c) 2023, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <nv_util.h>
#include <cstdio>
#include <hash_functions.cuh>
#include <limits>
#include "gpu_cache_api.hpp"
#ifdef LIBCUDACXX_VERSION
#include <cuda/atomic>
#include <cuda/semaphore>
#endif
#define SET_ASSOCIATIVITY 2
#define SLAB_SIZE 32
#define TASK_PER_WARP_TILE_MACRO 1
namespace gpu_cache {
// slab for static slab list
template <typename key_type, int warp_size>
struct static_slab {
key_type slab_[warp_size];
};
// Static slablist(slabset) for GPU Cache
template <int set_associativity, typename key_type, int warp_size>
struct slab_set {
static_slab<key_type, warp_size> set_[set_associativity];
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// GPU Cache
template <typename key_type, typename ref_counter_type, key_type empty_key, int set_associativity,
int warp_size, typename set_hasher = MurmurHash3_32<key_type>,
typename slab_hasher = Mod_Hash<key_type, size_t>>
class gpu_cache : public gpu_cache_api<key_type> {
public:
// Ctor
gpu_cache(const size_t capacity_in_set, const size_t embedding_vec_size);
// Dtor
~gpu_cache();
// Query API, i.e. A single read from the cache
void Query(const key_type* d_keys, const size_t len, float* d_values, uint64_t* d_missing_index,
key_type* d_missing_keys, size_t* d_missing_len, cudaStream_t stream,
const size_t task_per_warp_tile = TASK_PER_WARP_TILE_MACRO) override;
// Replace API, i.e. Follow the Query API to update the content of the cache to Most Recent
void Replace(const key_type* d_keys, const size_t len, const float* d_values, cudaStream_t stream,
const size_t task_per_warp_tile = TASK_PER_WARP_TILE_MACRO) override;
// Update API, i.e. update the embeddings which exist in the cache
void Update(const key_type* d_keys, const size_t len, const float* d_values, cudaStream_t stream,
const size_t task_per_warp_tile = TASK_PER_WARP_TILE_MACRO) override;
// Dump API, i.e. dump some slabsets' keys from the cache
void Dump(key_type* d_keys, size_t* d_dump_counter, const size_t start_set_index,
const size_t end_set_index, cudaStream_t stream) override;
void Record(cudaStream_t stream) override {}
public:
using slabset = slab_set<set_associativity, key_type, warp_size>;
#ifdef LIBCUDACXX_VERSION
using atomic_ref_counter_type = cuda::atomic<ref_counter_type, cuda::thread_scope_device>;
using mutex = cuda::binary_semaphore<cuda::thread_scope_device>;
#endif
private:
static const size_t BLOCK_SIZE_ = 64;
// Cache data
slabset* keys_;
float* vals_;
ref_counter_type* slot_counter_;
// Global counter
#ifdef LIBCUDACXX_VERSION
atomic_ref_counter_type* global_counter_;
#else
ref_counter_type* global_counter_;
#endif
// CUDA device
int dev_;
// Cache capacity
size_t capacity_in_set_;
size_t num_slot_;
// Embedding vector size
size_t embedding_vec_size_;
#ifdef LIBCUDACXX_VERSION
// Array of mutex to protect (sub-)warp-level data structure, each mutex protect 1 slab set
mutex* set_mutex_;
#else
// Array of flag to protect (sub-)warp-level data structure, each flag act as a mutex and protect
// 1 slab set 1 for unlock, 0 for lock
int* set_mutex_;
#endif
};
} // namespace gpu_cache