forked from apache/tvm
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Relay][Runtime] Add memory manager for NDArray (apache#3121)
* Add support for custom NDArray memory management Credit to @icemelon9 and @wweic * Fix copy-paste issue * Fix naive allocator.h * Remove buffer field * Apply Wei's suggestions. Co-Authored-By: jroesch <[email protected]> * Fix Wei's suggestion * Fix go rts * Break MM dependency * Add docs and clean up diff * Add more docs * Move to VM folder * Fix lint * Remove Go dep. * Rename to Empty * Address Haichen's comments
- Loading branch information
Showing
6 changed files
with
381 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you 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. | ||
*/ | ||
|
||
/*! | ||
* Copyright (c) 2019 by Contributors | ||
* \file tvm/runtime/memory_manager.cc | ||
* \brief Allocate and manage memory for the runtime. | ||
*/ | ||
#include <utility> | ||
#include <memory> | ||
#include "memory_manager.h" | ||
#include "naive_allocator.h" | ||
#include "pooled_allocator.h" | ||
|
||
namespace tvm { | ||
namespace runtime { | ||
namespace vm { | ||
|
||
MemoryManager* MemoryManager::Global() { | ||
static MemoryManager memory_manager; | ||
return &memory_manager; | ||
} | ||
|
||
Allocator* MemoryManager::GetAllocator(TVMContext ctx) { | ||
std::lock_guard<std::mutex> lock(mu_); | ||
if (allocators_.find(ctx) == allocators_.end()) { | ||
// LOG(INFO) << "New allocator for " << DeviceName(ctx.device_type) << "(" | ||
// << ctx.device_id << ")"; | ||
std::unique_ptr<Allocator> alloc(new NaiveAllocator(ctx)); | ||
allocators_.emplace(ctx, std::move(alloc)); | ||
} | ||
return allocators_.at(ctx).get(); | ||
} | ||
|
||
static void BufferDeleter(NDArray::Container* ptr) { | ||
CHECK(ptr->manager_ctx != nullptr); | ||
Buffer* buffer = reinterpret_cast<Buffer*>(ptr->manager_ctx); | ||
MemoryManager::Global()->GetAllocator(buffer->ctx)-> | ||
Free(*(buffer)); | ||
delete buffer; | ||
delete ptr; | ||
} | ||
|
||
NDArray Allocator::Empty(std::vector<int64_t> shape, DLDataType dtype, DLContext ctx) { | ||
VerifyDataType(dtype); | ||
NDArray::Container* container = new NDArray::Container(nullptr, shape, dtype, ctx); | ||
container->deleter = BufferDeleter; | ||
size_t size = GetDataSize(container->dl_tensor); | ||
size_t alignment = GetDataAlignment(container->dl_tensor); | ||
Buffer *buffer = new Buffer; | ||
*buffer = this->Alloc(size, alignment, dtype); | ||
container->manager_ctx = reinterpret_cast<void*>(buffer); | ||
container->dl_tensor.data = buffer->data; | ||
return NDArray(container); | ||
} | ||
|
||
} // namespace vm | ||
} // namespace runtime | ||
} // namespace tvm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you 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. | ||
*/ | ||
|
||
/*! | ||
* Copyright (c) 2019 by Contributors | ||
* \file src/runtime/memory_manager.h | ||
* \brief Abstract device memory management API | ||
*/ | ||
#ifndef TVM_RUNTIME_VM_MEMORY_MANAGER_H_ | ||
#define TVM_RUNTIME_VM_MEMORY_MANAGER_H_ | ||
|
||
#include <tvm/runtime/c_runtime_api.h> | ||
#include <functional> | ||
#include <memory> | ||
#include <mutex> | ||
#include <unordered_map> | ||
#include <vector> | ||
|
||
namespace std { | ||
template <> | ||
struct hash<TVMContext> { | ||
std::size_t operator()(const TVMContext& ctx) const { | ||
return ((ctx.device_id << 8) | ctx.device_type); | ||
} | ||
}; | ||
|
||
template <> | ||
struct equal_to<TVMContext> { | ||
bool operator()(const TVMContext& lhs, const TVMContext& rhs) const { | ||
return (lhs.device_type == rhs.device_type && lhs.device_id == rhs.device_id); | ||
} | ||
}; | ||
|
||
} // namespace std | ||
|
||
namespace tvm { | ||
namespace runtime { | ||
namespace vm { | ||
|
||
struct Buffer { | ||
/*! \brief The pointer to the allocated block of memory. */ | ||
void* data{nullptr}; | ||
/*! \brief The size of the block. */ | ||
size_t size{0}; | ||
/*! \brief The context of the allocated buffers. */ | ||
TVMContext ctx; | ||
}; | ||
|
||
class Allocator { | ||
public: | ||
Allocator() {} | ||
|
||
/*! \brief Allocate an empty NDArray using from the allocator. | ||
* \param shape The shape of the NDArray. | ||
* \param alignment The datatype of the NDArray. | ||
* \param ctx The context where the array is allocated. | ||
* \return The empty NDArray. | ||
*/ | ||
NDArray Empty(std::vector<int64_t> shape, | ||
DLDataType dtype, | ||
DLContext ctx); | ||
/*! \brief Allocate a buffer given a size, alignment and type. | ||
* \param nbytes The size of the buffer. | ||
* \param alignment The alignment of the buffer. | ||
* \param type_hint A type hint to the allocator. | ||
* \return A sized allocation in the form of a buffer. | ||
*/ | ||
virtual Buffer Alloc(size_t nbytes, size_t alignment, TVMType type_hint) = 0; | ||
/*! \brief Free a buffer allocated by the allocator. | ||
* \param buffer The buffer to free. | ||
*/ | ||
virtual void Free(const Buffer& buffer) = 0; | ||
/*! \brief The amount of memory currently allocated. | ||
* \return The amount of memory currently allocated. | ||
*/ | ||
virtual size_t UsedMemory() const = 0; | ||
virtual ~Allocator() = default; | ||
}; | ||
|
||
class MemoryManager { | ||
public: | ||
static MemoryManager* Global(); | ||
|
||
Allocator* GetAllocator(TVMContext ctx); | ||
|
||
private: | ||
MemoryManager() {} | ||
|
||
private: | ||
std::mutex mu_; | ||
std::unordered_map<TVMContext, std::unique_ptr<Allocator> > allocators_; | ||
}; | ||
|
||
} // namespace vm | ||
} // namespace runtime | ||
} // namespace tvm | ||
|
||
#endif // TVM_RUNTIME_VM_MEMORY_MANAGER_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you 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. | ||
*/ | ||
|
||
/*! | ||
* Copyright (c) 2019 by Contributors | ||
* \file src/runtime/naive_allocator.h | ||
*/ | ||
#ifndef TVM_RUNTIME_VM_NAIVE_ALLOCATOR_H_ | ||
#define TVM_RUNTIME_VM_NAIVE_ALLOCATOR_H_ | ||
|
||
#include <tvm/runtime/device_api.h> | ||
#include <atomic> | ||
|
||
#include "memory_manager.h" | ||
|
||
namespace tvm { | ||
namespace runtime { | ||
namespace vm { | ||
|
||
class NaiveAllocator final : public Allocator { | ||
public: | ||
explicit NaiveAllocator(TVMContext ctx) : Allocator(), used_memory_(0) {} | ||
|
||
Buffer Alloc(size_t nbytes, size_t alignment, TVMType type_hint) override { | ||
Buffer buf; | ||
buf.ctx = ctx_; | ||
buf.size = nbytes; | ||
buf.data = DeviceAPI::Get(ctx_)->AllocDataSpace(ctx_, nbytes, alignment, type_hint); | ||
used_memory_.fetch_add(nbytes, std::memory_order_relaxed); | ||
DLOG(INFO) << "allocate " << nbytes << " B, used memory " << used_memory_ << " B"; | ||
return buf; | ||
} | ||
|
||
void Free(const Buffer& buffer) override { | ||
DeviceAPI::Get(ctx_)->FreeDataSpace(buffer.ctx, buffer.data); | ||
used_memory_.fetch_sub(buffer.size, std::memory_order_relaxed); | ||
DLOG(INFO) << "free " << buffer.size << " B, used memory " << used_memory_ << " B"; | ||
} | ||
|
||
size_t UsedMemory() const override { | ||
return used_memory_.load(std::memory_order_relaxed); | ||
} | ||
|
||
private: | ||
std::atomic<size_t> used_memory_; | ||
TVMContext ctx_; | ||
}; | ||
|
||
} // namespace vm | ||
} // namespace runtime | ||
} // namespace tvm | ||
|
||
#endif // TVM_RUNTIME_VM_NAIVE_ALLOCATOR_H_ |
Oops, something went wrong.