Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions exec/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
include(CTest)

find_package(CUDAToolkit REQUIRED)

Expand All @@ -33,6 +34,15 @@ target_include_directories(flashrt_exec
${CMAKE_CURRENT_SOURCE_DIR}/backend)
target_link_libraries(flashrt_exec PUBLIC CUDA::cudart)

if(BUILD_TESTING)
add_executable(test_graph_lru_alloc tests/test_graph_lru_alloc.cpp)
target_include_directories(test_graph_lru_alloc PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(test_graph_lru_alloc PRIVATE flashrt_exec)
add_test(NAME graph_lru_alloc COMMAND test_graph_lru_alloc)
endif()

# --- pybind dev module (optional) ---
find_package(Python3 COMPONENTS Interpreter Development.Module QUIET)
find_package(pybind11 CONFIG QUIET)
Expand Down
5 changes: 4 additions & 1 deletion exec/src/graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

void frt_graph_s::touch(frt_shape_key key) {
for (auto it = lru.begin(); it != lru.end(); ++it) {
if (*it == key) { lru.erase(it); break; }
if (*it == key) {
lru.splice(lru.end(), lru, it);
return;
}
}
lru.push_back(key); // back = most recently used
}
Expand Down
61 changes: 61 additions & 0 deletions exec/tests/test_graph_lru_alloc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "internal.h"

#include <atomic>
#include <cstdlib>
#include <iostream>
#include <new>

namespace {

std::atomic<bool> count_allocations{false};
std::atomic<std::size_t> allocation_count{0};

[[noreturn]] void fail(const char* expression, int line) {
std::cerr << "FAIL line " << line << ": " << expression << '\n';
std::abort();
}

#define CHECK(expression) \
do { \
if (!(expression)) fail(#expression, __LINE__); \
} while (false)

} // namespace

void* operator new(std::size_t bytes) {
if (count_allocations.load(std::memory_order_relaxed)) {
allocation_count.fetch_add(1, std::memory_order_relaxed);
}
if (void* pointer = std::malloc(bytes)) return pointer;
throw std::bad_alloc();
}

void operator delete(void* pointer) noexcept { std::free(pointer); }
void operator delete(void* pointer, std::size_t) noexcept {
std::free(pointer);
}

int main() {
frt_graph_s graph;
graph.lru = {1, 2, 3};

allocation_count.store(0, std::memory_order_relaxed);
count_allocations.store(true, std::memory_order_relaxed);
for (int i = 0; i < 1000; ++i) graph.touch((i % 3) + 1);
count_allocations.store(false, std::memory_order_relaxed);

CHECK(allocation_count.load(std::memory_order_relaxed) == 0);
CHECK(graph.lru.size() == 3);
CHECK(graph.lru.back() == 1);

allocation_count.store(0, std::memory_order_relaxed);
count_allocations.store(true, std::memory_order_relaxed);
graph.touch(4);
count_allocations.store(false, std::memory_order_relaxed);
CHECK(allocation_count.load(std::memory_order_relaxed) > 0);
CHECK(graph.lru.size() == 4);
CHECK(graph.lru.back() == 4);

std::cout << "PASS - graph LRU touch allocation contract\n";
return 0;
}