@@ -1836,6 +1836,8 @@ static void destroy_hip_graphs(MIGraphXFuncState* mgx_state) {
18361836
18371837// Warmup run (ensures lazy GPU allocations are finalized) then capture the graph.
18381838// Stores extra (non-pre-allocated) output metadata so replay can materialize them.
1839+ static constexpr int kHipGraphWarmInIterations = 8 ;
1840+
18391841static bool warmup_and_capture_hip_graph (
18401842 MIGraphXFuncState* mgx_state,
18411843 hipStream_t stream,
@@ -1853,8 +1855,10 @@ static bool warmup_and_capture_hip_graph(
18531855 HIP_CALL_THROW (hipMemsetAsync (pin.data , 0 , pin.size_bytes , stream));
18541856 }
18551857
1858+ // Run multiple eager warmup iterations before capture to let MIGraphX
1859+ // internal workspace buffers (scratch, reductions, etc.) stabilize.
18561860 std::optional<migraphx::arguments> warmup_outputs;
1857- {
1861+ for ( int i = 0 ; i < kHipGraphWarmInIterations ; ++i) {
18581862 std::lock_guard<std::mutex> lock (*mgx_state->mgx_mu_ptr );
18591863 warmup_outputs = prog.run_async (m, stream);
18601864 }
@@ -1879,6 +1883,13 @@ static bool warmup_and_capture_hip_graph(
18791883 HIP_CALL_THROW (hipGraphInstantiate (&entry.exec , entry.graph , nullptr , nullptr , 0 ));
18801884 entry.captured = true ;
18811885
1886+ // Replay the captured graph several more times post-capture to ensure
1887+ // workspace is fully settled before the first real inference.
1888+ for (int i = 0 ; i < kHipGraphWarmInIterations ; ++i) {
1889+ HIP_CALL_THROW (hipGraphLaunch (entry.exec , stream));
1890+ }
1891+ HIP_CALL_THROW (hipStreamSynchronize (stream));
1892+
18821893 std::unordered_set<std::size_t > pre_alloc_set (prog_output_indices.begin (),
18831894 prog_output_indices.end ());
18841895 entry.extra_outputs .clear ();
@@ -1936,7 +1947,7 @@ static bool warmup_and_capture_hip_graph_direct(
19361947 const std::unordered_map<std::string, void *>& output_ptrs)
19371948{
19381949 std::optional<migraphx::arguments> warmup_outputs;
1939- {
1950+ for ( int i = 0 ; i < kHipGraphWarmInIterations ; ++i) {
19401951 std::lock_guard<std::mutex> lock (*mgx_state->mgx_mu_ptr );
19411952 warmup_outputs = prog.run_async (m, stream);
19421953 }
@@ -1963,6 +1974,11 @@ static bool warmup_and_capture_hip_graph_direct(
19631974 entry.captured_input_ptrs = input_ptrs;
19641975 entry.captured_output_ptrs = output_ptrs;
19651976
1977+ for (int i = 0 ; i < kHipGraphWarmInIterations ; ++i) {
1978+ HIP_CALL_THROW (hipGraphLaunch (entry.exec , stream));
1979+ }
1980+ HIP_CALL_THROW (hipStreamSynchronize (stream));
1981+
19661982 std::unordered_set<std::size_t > pre_alloc_set (prog_output_indices.begin (),
19671983 prog_output_indices.end ());
19681984 entry.extra_outputs .clear ();
0 commit comments