diff --git a/test/unified_memory_allocation/memoryPool.hpp b/test/unified_memory_allocation/memoryPool.hpp index c242419ba1..2c4186fe9a 100644 --- a/test/unified_memory_allocation/memoryPool.hpp +++ b/test/unified_memory_allocation/memoryPool.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #ifndef UMA_TEST_MEMORY_POOL_OPS_HPP #define UMA_TEST_MEMORY_POOL_OPS_HPP @@ -29,6 +30,7 @@ struct umaPoolTest : uma_test::test, return pool; } + static constexpr int NTHREADS = 5; uma::pool_unique_handle_t pool; }; @@ -57,6 +59,25 @@ TEST_P(umaPoolTest, allocFree) { umaPoolFree(pool.get(), ptr); } +// TEST_P(umaPoolTest, reallocFree) { +// static constexpr size_t allocSize = 64; +// static constexpr size_t multiplier = 3; +// auto *ptr = umaPoolMalloc(pool.get(), allocSize); +// ASSERT_NE(ptr, nullptr); +// auto *new_ptr = umaPoolRealloc(pool.get(), ptr, allocSize * multiplier); +// ASSERT_NE(new_ptr, nullptr); +// std::memset(new_ptr, 0, allocSize * multiplier); +// umaPoolFree(pool.get(), new_ptr); +// } + +// TEST_P(umaPoolTest, callocFree) { +// static constexpr size_t num = 10; +// static constexpr size_t size = sizeof(int); +// auto *ptr = umaPoolCalloc(pool.get(), num, size); +// ASSERT_NE(ptr, nullptr); +// umaPoolFree(pool.get(), ptr); +// } + TEST_P(umaPoolTest, pow2AlignedAlloc) { #ifdef _WIN32 // TODO: implement support for windows @@ -84,6 +105,189 @@ TEST_P(umaPoolTest, pow2AlignedAlloc) { } } +// TEST_P(umaPoolTest, allocZeroSize) { +// static constexpr size_t allocSize = 0; +// auto *ptr = umaPoolMalloc(pool.get(), allocSize); +// ASSERT_NE(ptr, nullptr); +// umaPoolFree(pool.get(), ptr); +// } + +TEST_P(umaPoolTest, freeNullptr) { + void *ptr = nullptr; + umaPoolFree(pool.get(), ptr); +} + +TEST_P(umaPoolTest, allocOutOfMem) { + // test whether memory is kept in a pool accordingly to MaxSize + static constexpr size_t allocSize = 16; + // MaxSize equals 16 * 1024 * 1024; + static constexpr size_t maxAllocs = 1024 * 1024; + + // allocate until oom + void *ptr = nullptr; + std::vector allocations; + + for (size_t i = 0; i <= maxAllocs; ++i) { + allocations.emplace_back(umaPoolMalloc(pool.get(), allocSize)); + ASSERT_NE(allocations.back(), nullptr); + } + + // check if the last allocation belongs to the pool + // it returns different values each time + // ASSERT_EQ(umaPoolByPtr(allocations.back()), pool.get()); + + // free some memory + umaPoolFree(pool.get(), allocations.back()); + + allocations.pop_back(); + + ptr = umaPoolMalloc(pool.get(), allocSize); + ASSERT_NE(ptr, nullptr); + + umaPoolFree(pool.get(), ptr); + + for (auto allocation : allocations) { + umaPoolFree(pool.get(), allocation); + } +} + +TEST_P(umaPoolTest, multiThreadedMallocFree) { + static constexpr size_t allocSize = 64; + auto poolMalloc = [](size_t allocSize, uma_memory_pool_handle_t pool) { + std::vector allocations; + for (size_t i = 0; i <= 10; ++i) { + allocations.emplace_back(umaPoolMalloc(pool, allocSize)); + ASSERT_NE(allocations.back(), nullptr); + } + + for (auto allocation : allocations) { + umaPoolFree(pool, allocation); + } + }; + + std::vector threads; + for (int i = 0; i < NTHREADS; i++) { + threads.push_back(std::thread(poolMalloc, allocSize, pool.get())); + } + + for (auto &thread : threads) { + thread.join(); + } +} + +TEST_P(umaPoolTest, multiThreadedpow2AlignedAlloc) { +#ifdef _WIN32 + // TODO: implement support for windows + GTEST_SKIP(); +#endif + + static constexpr size_t maxAlignment = (1u << 22); + static constexpr size_t numAllocs = 4; + auto poolPow2AlignedAlloc = [](size_t maxAlignment, size_t numAllocs, + uma_memory_pool_handle_t pool) { + for (size_t alignment = 1; alignment <= maxAlignment; alignment <<= 1) { + std::cout << alignment << std::endl; + std::vector allocs; + + for (size_t alloc = 0; alloc < numAllocs; alloc++) { + auto *ptr = umaPoolAlignedMalloc(pool, alignment, alignment); + ASSERT_NE(ptr, nullptr); + ASSERT_TRUE(reinterpret_cast(ptr) % alignment == 0); + std::memset(ptr, 0, alignment); + allocs.push_back(ptr); + } + + for (auto &ptr : allocs) { + umaPoolFree(pool, ptr); + } + } + }; + + std::vector threads; + for (int i = 0; i < NTHREADS; i++) { + threads.push_back(std::thread(poolPow2AlignedAlloc, maxAlignment, + numAllocs, pool.get())); + } + + for (auto &thread : threads) { + thread.join(); + } +} + +// TEST_P(umaPoolTest, multiThreadedReallocFree) { +// static constexpr size_t allocSize = 64; +// static constexpr multiplier = 3; +// auto poolRealloc = [](size_t allocSize, size_t multiplier, uma_memory_pool_handle_t pool) { +// std::vector allocations; +// for (size_t i = 0; i <= 10; ++i) { +// allocations.emplace_back(umaPoolMalloc(pool, allocSize)); +// ASSERT_NE(allocations.back(), nullptr); +// } + +// for (auto allocation : allocations) { +// auto *ptr = umaPoolRealloc(pool, allocation, allocSize * multiplier); +// umaPoolFree(pool, ptr); +// } +// }; + +// std::vector threads; +// for (int i = 0; i < NTHREADS; i++) { +// threads.push_back(std::thread(poolRealloc, allocSize, multiplier, pool.get())); +// } + +// for (auto &thread : threads) { +// thread.join(); +// } +// } + +// TEST_P(umaPoolTest, multiThreadedCallocFree) { +// static constexpr size_t num = 10; +// auto poolCalloc = [](size_t num, size_t size, +// uma_memory_pool_handle_t pool) { +// std::vector allocations; +// for (size_t i = 0; i <= 10; ++i) { +// allocations.emplace_back(umaPoolCalloc(pool, num, size)); +// ASSERT_NE(allocations.back(), nullptr); +// } + +// for (auto allocation : allocations) { +// umaPoolFree(pool, allocation); +// } +// }; + +// std::vector threads; +// for (int i = 0; i < NTHREADS; i++) { +// threads.push_back(std::thread(poolCalloc, 10, sizeof(int), pool.get())); +// } + +// for (auto &thread : threads) { +// thread.join(); +// } +// } + +TEST_P(umaPoolTest, multiThreadedMallocFreeRandomSizes) { + auto poolMalloc = [](size_t allocSize, uma_memory_pool_handle_t pool) { + std::vector allocations; + for (size_t i = 0; i <= 10; ++i) { + allocations.emplace_back(umaPoolMalloc(pool, allocSize)); + ASSERT_NE(allocations.back(), nullptr); + } + + for (auto allocation : allocations) { + umaPoolFree(pool, allocation); + } + }; + + std::vector threads; + for (int i = 0; i < NTHREADS; i++) { + threads.push_back(std::thread(poolMalloc, rand() % 64 + 1, pool.get())); + } + + for (auto &thread : threads) { + thread.join(); + } +} + // TODO: add similar tests for realloc/aligned_alloc, etc. // TODO: add multithreaded tests TEST_P(umaMultiPoolTest, memoryTracking) {