Skip to content

Dynamic concat gpu support#5032

Open
turneram wants to merge 18 commits into
developfrom
dynamic-concat-pointwise
Open

Dynamic concat gpu support#5032
turneram wants to merge 18 commits into
developfrom
dynamic-concat-pointwise

Conversation

@turneram

@turneram turneram commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Motivation

Dynamic concat is required to run dynamic kv-cache

Technical Details

Adds changes needed to run concat with dynamic shape inputs on gpu.

Changelog Category

Add a CHANGELOG.md entry for any option other than Not Applicable

    • Added: New functionality.
    • Changed: Changes to existing functionality.
    • Removed: Functionality or support that has been removed. (Compared to a previous release)
    • Optimized: Component performance that has been optimized or improved.
    • Resolved Issues: Known issues from a previous version that have been resolved.
    • Not Applicable: This PR is not to be included in the changelog.

@gh-app-migraphx-bot-pr-write

gh-app-migraphx-bot-pr-write Bot commented Jul 17, 2026

Copy link
Copy Markdown
Test Batch New Rate (e241fa) Old Rate (5c50d0) Diff Status
torchvision-resnet50 64 3,277.68 3,278.37 -0.02%
torchvision-resnet50_fp16 64 7,608.83 7,611.38 -0.03%
torchvision-densenet121 32 2,501.56 2,501.41 0.01%
torchvision-densenet121_fp16 32 4,987.90 5,004.64 -0.33%
torchvision-inceptionv3 32 1,241.95 2,059.27 -39.69% 🔴
torchvision-inceptionv3_fp16 32 4,382.53 4,417.65 -0.80%
cadene-inceptionv4 16 372.65 819.80 -54.54% 🔴
cadene-resnext64x4 16 782.55 783.52 -0.12%
slim-mobilenet 64 8,424.17 8,394.63 0.35%
slim-nasnetalarge 64 229.49 197.60 16.14% 🔆
slim-resnet50v2 64 1,323.37 3,185.87 -58.46% 🔴
bert-mrpc-onnx 8 362.43 1,161.65 -68.80% 🔴
bert-mrpc-tf 1 86.89 486.30 -82.13% 🔴
pytorch-examples-wlang-gru 1 192.95 469.65 -58.92% 🔴
pytorch-examples-wlang-lstm 1 197.06 379.72 -48.10% 🔴
torchvision-resnet50_1 1 1,036.03 1,023.59 1.22%
cadene-dpn92_1 1 217.71 436.69 -50.15% 🔴
cadene-resnext101_1 1 365.76 364.25 0.42%
onnx-taau-downsample 1 748.46 845.97 -11.53% 🔴
dlrm-criteoterabyte 1 32.66 32.54 0.38%
dlrm-criteoterabyte_fp16 1 52.71 52.59 0.22%
agentmodel 1 9,182.74 9,452.06 -2.85%
unet_fp16 2 47.50 59.01 -19.51% 🔴
resnet50v1_fp16 1 1,475.91 1,378.39 7.08% 🔆
resnet50v1_int8 1 1,617.66 1,626.43 -0.54%
bert_base_cased_fp16 64 1,102.25 1,102.97 -0.07%
bert_large_uncased_fp16 32 333.33 346.63 -3.84%
bert_large_fp16 1 28.53 205.51 -86.12% 🔴
distilgpt2_fp16 16 1,032.91 2,098.82 -50.79% 🔴
yolov5s 1 112.60 562.00 -79.96% 🔴
tinyllama 1 18.19 45.93 -60.39% 🔴
vicuna-fastchat 1 43.75 44.06 -0.70%
whisper-tiny-encoder 1 414.65 415.56 -0.22%
whisper-tiny-decoder 1 409.71 410.79 -0.26%
llama2_7b 1 20.94 21.01 -0.35%
qwen1.5-7b 1 23.65 23.60 0.22%
phi3-3.8b 1 26.84 26.80 0.12%
llama3-8b 1 21.84 21.70 0.64%
whisper-large-encoder 1 10.21 10.22 -0.03%
whisper-large-decoder 1 106.74 104.52 2.12%
mistral-7b 1 23.88 23.74 0.58%
FLUX.1-schnell 1 654.63 723.54 -9.52% 🔴

Regressions detected 🔴

@gh-app-migraphx-bot-pr-write

gh-app-migraphx-bot-pr-write Bot commented Jul 17, 2026

Copy link
Copy Markdown
Test Status Result
bert-mrpc-onnx PASSED: MIGraphX meets tolerance
bert-mrpc-tf PASSED: MIGraphX meets tolerance
pytorch-examples-wlang-gru PASSED: MIGraphX meets tolerance
pytorch-examples-wlang-lstm PASSED: MIGraphX meets tolerance
dlrm-criteoterabyte PASSED: MIGraphX meets tolerance
agentmodel PASSED: MIGraphX meets tolerance
unet PASSED: MIGraphX meets tolerance
resnet50v1 PASSED: MIGraphX meets tolerance
bert_base_cased_fp16 PASSED: MIGraphX meets tolerance
bert_large_uncased_fp16 🔴 FAILED: MIGraphX is not within tolerance - check verbose output
bert_large PASSED: MIGraphX meets tolerance
yolov5s PASSED: MIGraphX meets tolerance
tinyllama PASSED: MIGraphX meets tolerance
vicuna-fastchat PASSED: MIGraphX meets tolerance
whisper-tiny-encoder PASSED: MIGraphX meets tolerance
whisper-tiny-decoder PASSED: MIGraphX meets tolerance
distilgpt2_fp16 PASSED: MIGraphX meets tolerance
llama2_7b PASSED: MIGraphX meets tolerance
qwen1.5-7b PASSED: MIGraphX meets tolerance
phi3-3.8b PASSED: MIGraphX meets tolerance
llama3-8b PASSED: MIGraphX meets tolerance
whisper-large-encoder PASSED: MIGraphX meets tolerance
whisper-large-decoder PASSED: MIGraphX meets tolerance
mistral-7b PASSED: MIGraphX meets tolerance
FLUX.1-schnell PASSED: MIGraphX meets tolerance

@turneram
turneram marked this pull request as ready for review July 21, 2026 18:10
@turneram
turneram requested a review from causten as a code owner July 21, 2026 18:10
Comment thread src/targets/gpu/code_object_op.cpp Outdated
const char* ptr = arg.data();
if(ptr != nullptr and not is_device_ptr(ptr))
{
temps.push_back(to_gpu(arg));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The copies from host to device should happen in the IR not in the code object op. This can break hipgraph.

Comment on lines +133 to +135
std::transform(input_shapes.begin(), input_shapes.end(), std::back_inserter(params), [&](const auto& s) {
return m.add_parameter("x" + std::to_string(params.size()), s);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[format.py] reported by reviewdog 🐶

Suggested change
std::transform(input_shapes.begin(), input_shapes.end(), std::back_inserter(params), [&](const auto& s) {
return m.add_parameter("x" + std::to_string(params.size()), s);
});
std::transform(
input_shapes.begin(), input_shapes.end(), std::back_inserter(params), [&](const auto& s) {
return m.add_parameter("x" + std::to_string(params.size()), s);
});

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends MIGraphX’s GPU pipeline to support concat with dynamic-shape inputs (including a KV-cache-style “past + present” concat), primarily by ensuring host-resident inputs are moved to GPU memory before JIT compilation/execution and by updating the concat JIT compilation metadata to handle dynamic/output-alias cases.

Changes:

  • Insert hip::copy_to_gpu (with per-input allocations) for host inputs feeding dynamic concat precompile/dynamic-code-object ops during gpu::lower_device_ops.
  • Update GPU concat JIT compilation to carry num_concat_inputs and output_shape, and to avoid vectorization in output-alias and dynamic cases.
  • Add/adjust tests covering dynamic concat GPU lowering behavior and update ONNX clip dynamic tests for the new multibroadcast/common-args behavior.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/verify/test_dynamic_concat.cpp Adds verify-program coverage for dynamic concat patterns (axis0, KV-cache axis2, symbolic).
test/onnx/parse/clip_dyn_min_only_test.cpp Updates expected IR construction for dynamic clip min-only case using new multibroadcast wiring.
test/onnx/parse/clip_dyn_min_max_test.cpp Updates expected IR construction for dynamic clip min/max case; adds missing include for to_value.
test/gpu/lower_device_ops.cpp Adds unit tests asserting gpu::lower_device_ops inserts hip::copy_to_gpu only for dynamic concat cases.
src/targets/gpu/lower_device_ops.cpp Adds dynamic-concat input preparation (inserting hip::copy_to_gpu) and preserves module_inputs() on replace.
src/targets/gpu/jit/concat.cpp Extends concat JIT config to handle dynamic shapes/output aliasing; adjusts vectorization selection accordingly.
src/targets/gpu/include/migraphx/gpu/lower_device_ops.hpp Documents the expanded responsibilities of gpu::lower_device_ops.
src/targets/gpu/include/migraphx/gpu/hip.hpp Exposes is_device_ptr and simplifies hip_copy_to_gpu to use copy_to_gpu.
src/targets/gpu/hip.cpp Makes is_device_ptr non-static so it matches the new header declaration.
src/common.cpp Refactors dynamic multibroadcast insertion in insert_common_args to use an existing dynamic reference operand where possible.
Comments suppressed due to low confidence (2)

test/verify/test_dynamic_concat.cpp:74

  • The program does not add a return instruction, so the module has no outputs. Add an explicit mm->add_return({result}) after creating the concat instruction.
        auto past_key    = mm->add_parameter("past_key_values.0.key", past_shape);
        auto current_key = mm->add_literal(migraphx::generate_literal(current_shape));
        mm->add_instruction(migraphx::make_op("concat", {{"axis", 2}}), past_key, current_key);
        return p;

test/verify/test_dynamic_concat.cpp:104

  • The program does not add a return instruction, so the module has no outputs. Add an explicit return for the concat result.
        auto x   = mm->add_parameter("X", s0);
        auto y   = mm->add_parameter("Y", s1);
        auto z   = mm->add_parameter("Z", s2);
        mm->add_instruction(migraphx::make_op("concat", {{"axis", 0}}), x, y, z);
        return p;

Comment on lines +41 to +45
auto x = mm->add_parameter("X", s0);
auto y = mm->add_parameter("Y", s1);
auto z = mm->add_parameter("Z", s2);
mm->add_instruction(migraphx::make_op("concat", {{"axis", 0}}), x, y, z);
return p;
@pfultz2

pfultz2 commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

This seems confusing. It says its a dynamic concat input but it generates static JIT kernel.

Is this trying to implement a dynamic concat_past_present? It seems like insert slice op is a better choice.

@turneram

Copy link
Copy Markdown
Contributor Author

This seems confusing. It says its a dynamic concat input but it generates static JIT kernel.

Isn't that the current behavior for dynamic_code_object_op? Compiles static kernels for each value in {min,max}?

Is this trying to implement a dynamic concat_past_present? It seems like insert slice op is a better choice.

The pattern that's needed for at least the current model is this.

Old:
@0: past_key -> [batch,num_heads,past_sl=MAX_SL,head_size]
@1: present_key -> [batch,num_heads,sl=1,head_size]
@2: concat_past_present(@0,@1) -> [batch,num_heads,past_sl=MAX_SL,head_size]
@3: attention(@2,...)

Dynamic past-seq-len:
@0: past_key -> [batch,num_heads,past_sl={min:0, max:MAX_SL-1},head_size]
@1: present_key -> [batch,num_heads,sl=1,head_size]
@2: concat(@0,@1) -> [batch,num_heads,total_sl={min:1, max:MAX_SL},head_size]
@3: fixed_pad(@2) - > [batch,num_heads,MAX_SL,head_size]
@3: attention(@3,...)

@kahmed10
kahmed10 requested a review from shivadbhavsar July 23, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants