diff --git a/examples/RocprofOnDemandRepro/Makefile b/examples/RocprofOnDemandRepro/Makefile index 0a03cf70..3e00f551 100644 --- a/examples/RocprofOnDemandRepro/Makefile +++ b/examples/RocprofOnDemandRepro/Makefile @@ -4,12 +4,13 @@ CXX := g++ ROCM_LIB := /opt/rocm/lib TRACY_SRCS := $(TRACY_PUBLIC)/TracyClient.cpp -INCLUDES := -I$(TRACY_PUBLIC) +ROCM_INC := /opt/rocm/include +INCLUDES := -I$(TRACY_PUBLIC) -I$(ROCM_INC) LIBS := -L$(ROCM_LIB) -lrocprofiler-sdk -lpthread -ldl # On-demand mode (the default for this repro) — profiling starts when # a client connects, not at program launch. -DEFINES := -DTRACY_ENABLE -DTRACY_ON_DEMAND -DTRACY_ROCPROF +DEFINES := -DTRACY_ENABLE -DTRACY_ON_DEMAND -DTRACY_ROCPROF -D__HIP_PLATFORM_AMD__ CXXFLAGS := -O2 $(DEFINES) HIPCCFLAGS := -O2 $(DEFINES) @@ -17,11 +18,14 @@ HIPCCFLAGS := -O2 $(DEFINES) all: repro -repro: repro.cpp tracy_client.o - $(HIPCC) $(HIPCCFLAGS) $(INCLUDES) -o $@ $< tracy_client.o $(LIBS) +repro: repro.o tracy_client.o + $(HIPCC) -o $@ $^ $(LIBS) + +repro.o: repro.cpp + $(HIPCC) $(HIPCCFLAGS) $(INCLUDES) -c -o $@ $< tracy_client.o: $(TRACY_SRCS) $(CXX) $(CXXFLAGS) $(INCLUDES) -c -o $@ $< clean: - rm -f repro tracy_client.o + rm -f repro repro.o tracy_client.o diff --git a/examples/RocprofOnDemandRepro/README.md b/examples/RocprofOnDemandRepro/README.md index 6f8355c3..8707707e 100644 --- a/examples/RocprofOnDemandRepro/README.md +++ b/examples/RocprofOnDemandRepro/README.md @@ -5,7 +5,7 @@ HIP application built with `TRACY_ON_DEMAND` and `TRACY_ROCPROF`. ## Root cause -Two bugs in `TracyRocprof.cpp` break on-demand profiling: +Three bugs in `TracyRocprof.cpp` break on-demand profiling: 1. **GpuNewContext not deferred.** `gpu_context_allocate()` writes a `GpuNewContext` queue item but does not call `DeferItem()`. When a @@ -15,7 +15,12 @@ Two bugs in `TracyRocprof.cpp` break on-demand profiling: Assertion `ctx' failed in ProcessGpuZoneBeginImplCommon -2. **Kernel symbols dropped before init.** The `data->init` guard at the +2. **GpuContextName not deferred.** Same function writes the context + name ("rocprofv3") without calling `DeferItem()`. Even after fixing + bug 1, a late-connecting client sees the GPU context but it appears + unnamed in the profiler. Use `check_gpu_ctx_name` to verify. + +3. **Kernel symbols dropped before init.** The `data->init` guard at the top of `tool_callback_tracing_callback()` blocks all callbacks before the GPU context is allocated. Kernel symbol registrations (`CODE_OBJECT_DEVICE_KERNEL_SYMBOL_REGISTER`) happen at HIP init @@ -36,9 +41,24 @@ make tracy-capture -o repro.tracy -s 5 ``` +## Verifying the context name + +`check_gpu_ctx_name` loads a `.tracy` file and prints the GPU context +names. Build it against the Tracy server library (e.g. from a capture +build directory) and run: + +```bash +./check_gpu_ctx_name repro.tracy +# Expected (patched): "GPU context 0: rocprofv3" +# Expected (unpatched): "GPU context 0: (unnamed)" +``` + +Exit codes: 0 = all contexts named, 2 = unnamed context found. + ## What to expect | Tracy version | Result | |---|---| | Unpatched | `tracy-capture` crashes: `Assertion 'ctx' failed` | -| Patched | Capture succeeds with ~50 GPU zones (`vectorAdd`) with kernel names | +| Patched (GpuNewContext only) | Capture succeeds but GPU context is unnamed | +| Fully patched | Capture succeeds with ~50 GPU zones and context named "rocprofv3" | diff --git a/examples/RocprofOnDemandRepro/check_gpu_ctx_name.cpp b/examples/RocprofOnDemandRepro/check_gpu_ctx_name.cpp new file mode 100644 index 00000000..b24dfc8e --- /dev/null +++ b/examples/RocprofOnDemandRepro/check_gpu_ctx_name.cpp @@ -0,0 +1,65 @@ +// Loads a .tracy file and prints the GPU context names. +// Used to verify that on-demand profiling correctly defers the +// GpuContextName message so late-connecting clients see the name. +// +// Usage: ./check_gpu_ctx_name trace.tracy +// Expected output: "GPU context 0: rocprofv3" +// If name is missing: "GPU context 0: (unnamed)" + +#include +#include +#include "server/TracyFileRead.hpp" +#include "server/TracyWorker.hpp" + +int main( int argc, char** argv ) +{ + if( argc != 2 ) + { + fprintf( stderr, "Usage: %s \n", argv[0] ); + return 1; + } + + try + { + auto f = std::unique_ptr( tracy::FileRead::Open( argv[1] ) ); + if( !f ) + { + fprintf( stderr, "Cannot open %s\n", argv[1] ); + return 1; + } + + tracy::Worker worker( *f, tracy::EventType::None, false ); + + const auto& gpuData = worker.GetGpuData(); + if( gpuData.empty() ) + { + printf( "No GPU contexts found.\n" ); + return 1; + } + + bool all_named = true; + for( size_t i = 0; i < gpuData.size(); i++ ) + { + const auto& ctx = gpuData[i]; + if( ctx->name.Active() ) + { + const char* name = worker.GetString( ctx->name ); + bool has_name = name && name[0] != '\0'; + printf( "GPU context %zu: %s\n", i, has_name ? name : "(unnamed)" ); + if( !has_name ) all_named = false; + } + else + { + printf( "GPU context %zu: (unnamed)\n", i ); + all_named = false; + } + } + + return all_named ? 0 : 2; + } + catch( const std::exception& e ) + { + fprintf( stderr, "Error: %s\n", e.what() ); + return 1; + } +} diff --git a/public/client/TracyRocprof.cpp b/public/client/TracyRocprof.cpp index e7744a62..c0d9a23a 100644 --- a/public/client/TracyRocprof.cpp +++ b/public/client/TracyRocprof.cpp @@ -124,6 +124,9 @@ uint8_t gpu_context_allocate( ToolData* data ) tracy::MemWrite( &item->gpuContextNameFat.context, context_id ); tracy::MemWrite( &item->gpuContextNameFat.ptr, (uint64_t)cloned_name ); tracy::MemWrite( &item->gpuContextNameFat.size, name_length ); +#ifdef TRACY_ON_DEMAND + GetProfiler().DeferItem( *item ); +#endif tracy::Profiler::QueueSerialFinish(); }