1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
#include <gtest/gtest.h>
#include <array>
#include <set>
#include "include/libkineto.h"
#include "include/Config.h"
#include "src/CuptiRangeProfilerApi.h"
#include "src/Logger.h"
#include "test/CuptiRangeProfilerTestUtil.h"
using namespace KINETO_NAMESPACE;
#if HAS_CUPTI_RANGE_PROFILER
std::unordered_map<int, CuptiProfilerResult>&
MockCuptiRBProfilerSession::getResults() {
static std::unordered_map<int, CuptiProfilerResult> results;
return results;
}
MockCuptiRBProfilerSessionFactory mfactory{};
TEST(CuptiRangeProfilerApiTest, contextTracking) {
std::vector<std::string> log_modules(
{"CuptiRangeProfilerApi.cpp"});
SET_LOG_VERBOSITY_LEVEL(1, log_modules);
std::array<int64_t, 3> data;
std::array<CUcontext, 3> contexts;
for (int i = 0; i < data.size(); i++) {
contexts[i] = reinterpret_cast<CUcontext>(&data[i]);
}
// simulate creating contexts, this calls the trackCudaContexts
// function that would otherwise be called via a callback
uint32_t dev = 0;
for (auto ctx : contexts) {
simulateCudaContextCreate(ctx, dev++);
}
EXPECT_EQ(
CuptiRBProfilerSession::getActiveDevices(),
std::set<uint32_t>({0, 1, 2}));
simulateCudaContextDestroy(contexts[1], 1);
EXPECT_EQ(
CuptiRBProfilerSession::getActiveDevices(),
std::set<uint32_t>({0, 2}));
simulateCudaContextDestroy(contexts[0], 0);
simulateCudaContextDestroy(contexts[2], 2);
EXPECT_TRUE(
CuptiRBProfilerSession::getActiveDevices().empty());
}
TEST(CuptiRangeProfilerApiTest, asyncLaunchUserRange) {
std::vector<std::string> log_modules(
{"CuptiRangeProfilerApi.cpp"});
SET_LOG_VERBOSITY_LEVEL(1, log_modules);
// this is bad but the pointer is never accessed
CUcontext ctx0 = reinterpret_cast<CUcontext>(10);
simulateCudaContextCreate(ctx0, 0 /*device_id*/);
CuptiRangeProfilerOptions opts{
.deviceId = 0,
.cuContext = ctx0};
std::unique_ptr<CuptiRBProfilerSession> session_ = mfactory.make(opts);
auto session = mfactory.asDerived(session_.get());
session->asyncStartAndEnable(CUPTI_UserRange, CUPTI_UserReplay);
simulateKernelLaunch(ctx0, "hello");
simulateKernelLaunch(ctx0, "foo");
simulateKernelLaunch(ctx0, "bar");
session->asyncDisableAndStop();
// stop happens after next kernel is run
simulateKernelLaunch(ctx0, "bar");
simulateCudaContextDestroy(ctx0, 0 /*device_id*/);
EXPECT_EQ(session->passes_ended, 1);
EXPECT_EQ(session->ranges_ended, 1);
EXPECT_TRUE(session->enabled);
}
TEST(CuptiRangeProfilerApiTest, asyncLaunchAutoRange) {
std::vector<std::string> log_modules(
{"CuptiRangeProfilerApi.cpp"});
SET_LOG_VERBOSITY_LEVEL(1, log_modules);
// this is bad but the pointer is never accessed
CUcontext ctx0 = reinterpret_cast<CUcontext>(10);
CUcontext ctx1 = reinterpret_cast<CUcontext>(11);
simulateCudaContextCreate(ctx0, 0 /*device_id*/);
CuptiRangeProfilerOptions opts{
.deviceId = 0,
.cuContext = ctx0};
std::unique_ptr<CuptiRBProfilerSession> session_ = mfactory.make(opts);
auto session = mfactory.asDerived(session_.get());
session->asyncStartAndEnable(CUPTI_AutoRange, CUPTI_KernelReplay);
simulateKernelLaunch(ctx0, "hello");
simulateKernelLaunch(ctx0, "foo");
simulateKernelLaunch(ctx1, "kernel_on_different_device");
simulateKernelLaunch(ctx0, "bar");
session->asyncDisableAndStop();
// stop happens after next kernel is run
simulateKernelLaunch(ctx0, "bar");
simulateCudaContextDestroy(ctx0, 0 /*device_id*/);
EXPECT_EQ(session->passes_ended, 0);
EXPECT_EQ(session->ranges_ended, 0);
EXPECT_TRUE(session->enabled);
EXPECT_EQ(
session->getKernelNames(),
std::vector<std::string>({"hello", "foo", "bar"}))
<< "Kernel names were not tracked";
}
#endif // HAS_CUPTI_RANGE_PROFILER
|