/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the CC-by-NC license found in the * LICENSE file in the root directory of this source tree. */ // Copyright 2004-present Facebook. All Rights Reserved. #pragma once #include "DeviceMemory.h" #include #include #include namespace faiss { namespace gpu { /// Device memory manager that provides temporary memory allocations /// out of a region of memory class StackDeviceMemory : public DeviceMemory { public: /// Allocate a new region of memory that we manage explicit StackDeviceMemory(int device, size_t allocPerDevice); /// Manage a region of memory for a particular device, with or /// without ownership StackDeviceMemory(int device, void* p, size_t size, bool isOwner); ~StackDeviceMemory() override; int getDevice() const override; DeviceMemoryReservation getMemory(cudaStream_t stream, size_t size) override; size_t getSizeAvailable() const override; std::string toString() const override; size_t getHighWaterCudaMalloc() const override; protected: void returnAllocation(DeviceMemoryReservation& m) override; protected: /// Previous allocation ranges and the streams for which /// synchronization is required struct Range { inline Range(char* s, char* e, cudaStream_t str) : start_(s), end_(e), stream_(str) { } // References a memory range [start, end) char* start_; char* end_; cudaStream_t stream_; }; struct Stack { /// Constructor that allocates memory via cudaMalloc Stack(int device, size_t size); /// Constructor that references a pre-allocated region of memory Stack(int device, void* p, size_t size, bool isOwner); ~Stack(); /// Returns how much size is available for an allocation without /// calling cudaMalloc size_t getSizeAvailable() const; /// Obtains an allocation; all allocations are guaranteed to be 16 /// byte aligned char* getAlloc(size_t size, cudaStream_t stream); /// Returns an allocation void returnAlloc(char* p, size_t size, cudaStream_t stream); /// Returns the stack state std::string toString() const; /// Returns the high-water mark of cudaMalloc activity size_t getHighWaterCudaMalloc() const; /// Device this allocation is on int device_; /// Do we own our region of memory? bool isOwner_; /// Where our allocation begins and ends /// [start_, end_) is valid char* start_; char* end_; /// Total size end_ - start_ size_t size_; /// Stack head within [start, end) char* head_; /// List of previous last users of allocations on our stack, for /// possible synchronization purposes std::list lastUsers_; /// How much cudaMalloc memory is currently outstanding? size_t mallocCurrent_; /// What's the high water mark in terms of memory used from the /// temporary buffer? size_t highWaterMemoryUsed_; /// What's the high water mark in terms of memory allocated via /// cudaMalloc? size_t highWaterMalloc_; }; /// Our device int device_; /// Memory stack Stack stack_; }; } } // namespace