-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[VM][OpenCL] Introduce textures allocation to VM memory manager (#15400)
* [VM][OpenCL] Introduce textures allocation to VM memory manager VM memory manager is extended to support allocation memory with different memory scope. This functionality is fully implemented for naive allocator. For pooled allocator is should be implemented in the future. * Fix lint * Fix OpenCL tests
- Loading branch information
Showing
5 changed files
with
275 additions
and
1 deletion.
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
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,204 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
#include <gmock/gmock.h> | ||
#include <gtest/gtest.h> | ||
#include <tvm/runtime/vm/memory_manager.h> | ||
|
||
#include <exception> | ||
|
||
#include "../../../../src/runtime/vm/pooled_allocator.h" | ||
|
||
namespace tvm { | ||
namespace runtime { | ||
namespace vm { | ||
|
||
// MemoryManangerWrapper is necessary because in class MemoryManager we don't have access to its | ||
// protected members. In this class we add a new method which allow us to clear internal state of | ||
// the global memory manager. | ||
class MemoryManagerWrapper : public MemoryManager { | ||
public: | ||
static MemoryManagerWrapper* Global() { | ||
return reinterpret_cast<MemoryManagerWrapper*>(MemoryManager::Global()); | ||
} | ||
void clear() { allocators_.clear(); } | ||
}; | ||
|
||
class TvmVMMemoryManagerTest : public ::testing::Test { | ||
protected: | ||
void SetUp() override { | ||
// Clear allocators from previous tests | ||
MemoryManagerWrapper::Global()->clear(); | ||
} | ||
}; | ||
|
||
TEST_F(TvmVMMemoryManagerTest, NaiveAllocBasic) { | ||
Device dev = {kDLCPU, 0}; | ||
Allocator* allocator = MemoryManagerWrapper::GetOrCreateAllocator(dev, kNaive); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
auto buff = allocator->Alloc(64, 32, DataType::Float(32)); | ||
EXPECT_EQ(allocator->UsedMemory(), 64); | ||
allocator->Free(buff); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
} | ||
|
||
TEST_F(TvmVMMemoryManagerTest, PooledAllocBasic) { | ||
Device dev = {kDLCPU, 0}; | ||
size_t nbytes = 64; | ||
size_t page_size = PooledAllocator::kDefaultPageSize; | ||
size_t size = ((nbytes + page_size - 1) / page_size) * page_size; | ||
Allocator* allocator = MemoryManagerWrapper::GetOrCreateAllocator(dev, kPooled); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
auto buff = allocator->Alloc(nbytes, 32, DataType::Float(32)); | ||
EXPECT_EQ(allocator->UsedMemory(), size); | ||
allocator->Free(buff); | ||
EXPECT_EQ(allocator->UsedMemory(), size); | ||
} | ||
|
||
TEST_F(TvmVMMemoryManagerTest, NaiveEmptyBasic) { | ||
Device dev = {kDLCPU, 0}; | ||
Allocator* allocator = MemoryManagerWrapper::GetOrCreateAllocator(dev, kNaive); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
auto dt = DataType::Float(32); | ||
size_t nbytes = 1 * 3 * 6 * 6 * dt.bytes(); | ||
std::vector<int64_t> shape = {1, 3, 6, 6}; | ||
{ | ||
auto ndarray = allocator->Empty(shape, dt, dev); | ||
EXPECT_EQ(allocator->UsedMemory(), nbytes); | ||
} | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
} | ||
|
||
TEST_F(TvmVMMemoryManagerTest, PooledEmptyBasic) { | ||
Device dev = {kDLCPU, 0}; | ||
Allocator* allocator = MemoryManagerWrapper::GetOrCreateAllocator(dev, kPooled); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
auto dt = DataType::Float(32); | ||
size_t nbytes = 1 * 3 * 6 * 6 * dt.bytes(); | ||
size_t page_size = PooledAllocator::kDefaultPageSize; | ||
size_t size = ((nbytes + page_size - 1) / page_size) * page_size; | ||
std::vector<int64_t> shape = {1, 3, 6, 6}; | ||
{ | ||
auto ndarray = allocator->Empty(shape, dt, dev); | ||
EXPECT_EQ(allocator->UsedMemory(), size); | ||
} | ||
EXPECT_EQ(allocator->UsedMemory(), size); | ||
} | ||
|
||
TEST_F(TvmVMMemoryManagerTest, NaiveAllocWithShape) { | ||
Device dev = {kDLCPU, 0}; | ||
Allocator* allocator = MemoryManagerWrapper::GetOrCreateAllocator(dev, kNaive); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
auto dt = DataType::Float(32); | ||
size_t nbytes = 1 * 3 * 6 * 6 * dt.bytes(); | ||
std::vector<int64_t> shape = {1, 3, 6, 6}; | ||
auto buff = allocator->Alloc(shape.size(), shape.data(), dt); | ||
EXPECT_EQ(allocator->UsedMemory(), nbytes); | ||
allocator->Free(buff); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
|
||
try { | ||
auto texture = allocator->Alloc(shape.size(), shape.data(), dt, "global.texture"); | ||
FAIL(); | ||
} catch (std::exception& e) { | ||
std::string pattern = | ||
"Device does not support allocate data space with specified memory scope: global.texture"; | ||
std::string what = e.what(); | ||
EXPECT_NE(what.find(pattern), std::string::npos) << what; | ||
} | ||
} | ||
|
||
TEST_F(TvmVMMemoryManagerTest, PooledAllocWithShape) { | ||
Device dev = {kDLCPU, 0}; | ||
Allocator* allocator = MemoryManagerWrapper::GetOrCreateAllocator(dev, kPooled); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
auto dt = DataType::Float(32); | ||
size_t nbytes = 1 * 3 * 6 * 6 * dt.bytes(); | ||
size_t page_size = PooledAllocator::kDefaultPageSize; | ||
size_t size = ((nbytes + page_size - 1) / page_size) * page_size; | ||
std::vector<int64_t> shape = {1, 3, 6, 6}; | ||
auto buff = allocator->Alloc(shape.size(), shape.data(), dt); | ||
EXPECT_EQ(allocator->UsedMemory(), size); | ||
allocator->Free(buff); | ||
EXPECT_EQ(allocator->UsedMemory(), size); | ||
|
||
try { | ||
auto texture = allocator->Alloc(shape.size(), shape.data(), dt, "global.texture"); | ||
FAIL(); | ||
} catch (std::exception& e) { | ||
std::string pattern = "This alloc should be implemented"; | ||
std::string what = e.what(); | ||
EXPECT_NE(what.find(pattern), std::string::npos) << what; | ||
} | ||
} | ||
|
||
TEST_F(TvmVMMemoryManagerTest, NaiveAllocOpenCLTexture) { | ||
bool enabled = tvm::runtime::RuntimeEnabled("opencl"); | ||
if (!enabled) { | ||
LOG(INFO) << "Skip OpenCL Texture alloc test because opencl runtime is disabled.\n"; | ||
return; | ||
} | ||
Device dev = {kDLOpenCL, 0}; | ||
Allocator* allocator = MemoryManagerWrapper::GetOrCreateAllocator(dev, kNaive); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
auto dt = DataType::Float(32); | ||
size_t nbytes = 1 * 3 * 6 * 6 * dt.bytes(); | ||
std::vector<int64_t> shape = {1, 3, 6, 6}; | ||
auto buff = allocator->Alloc(shape.size(), shape.data(), dt); | ||
EXPECT_EQ(allocator->UsedMemory(), nbytes); | ||
allocator->Free(buff); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
|
||
auto texture = allocator->Alloc(shape.size(), shape.data(), dt, "global.texture"); | ||
EXPECT_EQ(allocator->UsedMemory(), nbytes); | ||
allocator->Free(texture); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
} | ||
|
||
TEST_F(TvmVMMemoryManagerTest, PooledAllocOpenCLTexture) { | ||
bool enabled = tvm::runtime::RuntimeEnabled("opencl"); | ||
if (!enabled) { | ||
LOG(INFO) << "Skip OpenCL Texture alloc test because opencl runtime is disabled.\n"; | ||
return; | ||
} | ||
Device dev = {kDLOpenCL, 0}; | ||
Allocator* allocator = MemoryManagerWrapper::GetOrCreateAllocator(dev, kPooled); | ||
EXPECT_EQ(allocator->UsedMemory(), 0); | ||
auto dt = DataType::Float(32); | ||
size_t nbytes = 1 * 3 * 6 * 6 * dt.bytes(); | ||
size_t page_size = PooledAllocator::kDefaultPageSize; | ||
size_t size = ((nbytes + page_size - 1) / page_size) * page_size; | ||
std::vector<int64_t> shape = {1, 3, 6, 6}; | ||
auto buff = allocator->Alloc(shape.size(), shape.data(), dt); | ||
EXPECT_EQ(allocator->UsedMemory(), size); | ||
allocator->Free(buff); | ||
EXPECT_EQ(allocator->UsedMemory(), size); | ||
|
||
try { | ||
auto texture = allocator->Alloc(shape.size(), shape.data(), dt, "global.texture"); | ||
FAIL(); | ||
} catch (std::exception& e) { | ||
std::string pattern = "This alloc should be implemented"; | ||
std::string what = e.what(); | ||
EXPECT_NE(what.find(pattern), std::string::npos) << what; | ||
} | ||
} | ||
} // namespace vm | ||
} // namespace runtime | ||
} // namespace tvm |