Skip to content

Eval bug: GGML_ASSERT(n_inputs < GGML_SCHED_MAX_SPLIT_INPUTS) failed on DS v4 Flash on single GPU #25800

Closed

Description

@eapache

Name and Version

version: 10055 (e8f19cc)
built with GNU 13.3.0 for Linux x86_64

Operating systems

Linux

GGML backends

CUDA

Hardware

Ryzen 9900X + RTX3060

Models

DeepSeek-V4-Flash-UD-IQ2_M from https://huggingface.co/unsloth/DeepSeek-V4-Flash-GGUF

Problem description & steps to reproduce

Simply try to start it with a large-ish context:

./build/bin/llama-cli -c 65536 -m models/custom/Deepseek-V4-Flash/DeepSeek-V4-Flash-UD-IQ2_M-00001-of-00003.gguf

Starting it with a smaller context works fine, e.g.:

./build/bin/llama-cli -c 32768 -m models/custom/Deepseek-V4-Flash/DeepSeek-V4-Flash-UD-IQ2_M-00001-of-00003.gguf

Since I only have a 3060 (12GB) and it seems limited to large contexts, I suspect something to do with memory pressure on the GPU that is not falling back to the CPU properly (or is just bailing before CUDA can fail to alloc)?

First Bad Commit

0dc74e3 / #25585

Relevant log output

Logs
$ ./build/bin/llama-cli -c 65536 -m models/custom/Deepseek-V4-Flash/DeepSeek-V4-Flash-UD-IQ2_M-00001-of-00003.gguf 


Loading model... -/home/eapache/src/llama.cpp/ggml/src/ggml-backend.cpp:1367: GGML_ASSERT(n_inputs < GGML_SCHED_MAX_SPLIT_INPUTS) failed
\[New LWP 22798]
[New LWP 22797]
[New LWP 22796]
[New LWP 22795]
[New LWP 22794]
[New LWP 22793]
[New LWP 22792]
[New LWP 22791]
[New LWP 22790]
[New LWP 22789]
[New LWP 22788]
[New LWP 22787]
[New LWP 22786]
[New LWP 22785]
[New LWP 22784]
[New LWP 22783]
[New LWP 22782]
[New LWP 22781]
[New LWP 22780]
[New LWP 22779]
[New LWP 22778]
[New LWP 22777]
[New LWP 22776]
[New LWP 22775]
[New LWP 22774]
[New LWP 22773]
[New LWP 22772]
[New LWP 22771]
[New LWP 22770]
[New LWP 22769]
[New LWP 22765]

This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n]) [answered N; input not from terminal]
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007535168ecadf in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=0x7ffcdaa09df0, rem=0x7ffcdaa09df0) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78
warning: 78	../sysdeps/unix/sysv/linux/clock_nanosleep.c: No such file or directory
#0  0x00007535168ecadf in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=0x7ffcdaa09df0, rem=0x7ffcdaa09df0) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78
78	in ../sysdeps/unix/sysv/linux/clock_nanosleep.c
#1  0x00007535168f9a27 in __GI___nanosleep (req=<optimized out>, rem=<optimized out>) at ../sysdeps/unix/sysv/linux/nanosleep.c:25
warning: 25	../sysdeps/unix/sysv/linux/nanosleep.c: No such file or directory
#2  0x00007535176aefd5 in cli_server::wait_ready(std::function<bool ()>) () from /home/eapache/src/llama.cpp/build/bin/libllama-cli-impl.so
#3  0x00007535176a9000 in cli_context::init() () from /home/eapache/src/llama.cpp/build/bin/libllama-cli-impl.so
#4  0x00007535176911dc in llama_cli(int, char**) () from /home/eapache/src/llama.cpp/build/bin/libllama-cli-impl.so
#5  0x000075351682a1ca in __libc_start_call_main (main=main@entry=0x5c0c9addd5d0 <main>, argc=argc@entry=5, argv=argv@entry=0x7ffcdaa0d858) at ../sysdeps/nptl/libc_start_call_main.h:58
warning: 58	../sysdeps/nptl/libc_start_call_main.h: No such file or directory
#6  0x000075351682a28b in __libc_start_main_impl (main=0x5c0c9addd5d0 <main>, argc=5, argv=0x7ffcdaa0d858, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffcdaa0d848) at ../csu/libc-start.c:360
warning: 360	../csu/libc-start.c: No such file or directory
#7  0x00005c0c9addd605 in _start ()
|[Inferior 1 (process 22762) detached]
Aborted (core dumped)

Activity

  1. eapache commented on Jul 17, 2026

    @eapache
    ContributorAuthor

    I have the full core dump file locally if more detail is needed. The actual relevant backtrace looks to be

    #5  0x000079b3b794d806 in ggml_abort () from /home/eapache/src/llama.cpp/build/bin/libggml-base.so.0
    #6  0x000079b3b796a50f in ggml_backend_sched_split_graph () from /home/eapache/src/llama.cpp/build/bin/libggml-base.so.0
    #7  0x000079b3b60f2062 in llama_context::graph_reserve(unsigned int, unsigned int, unsigned int, llama_memory_context_i const*, bool, unsigned long*) ()
       from /home/eapache/src/llama.cpp/build/bin/libllama.so.0
    #8  0x000079b3b60f361c in llama_context::sched_reserve() () from /home/eapache/src/llama.cpp/build/bin/libllama.so.0
    #9  0x000079b3b60f6c69 in llama_context::llama_context(llama_model const&, llama_context_params) () from /home/eapache/src/llama.cpp/build/bin/libllama.so.0
    #10 0x000079b3b60f7d72 in llama_init_from_model () from /home/eapache/src/llama.cpp/build/bin/libllama.so.0
    #11 0x000079b3b6643509 in common_get_device_memory_data_impl(char const*, llama_model_params const*, llama_context_params const*, std::vector<ggml_backend_device*, std::allocator<ggml_backend_device*> >&, unsigned int&, unsigned int&, unsigned int&, ggml_log_level) () from /home/eapache/src/llama.cpp/build/bin/libllama-common.so.0
    #12 0x000079b3b66442c0 in common_params_fit_impl(char const*, llama_model_params*, llama_context_params*, float*, llama_model_tensor_buft_override*, unsigned long*, unsigned int, ggml_log_level)::{lambda(char const*, std::vector<common_params_fit_impl(char const*, llama_model_params*, llama_context_params*, float*, llama_model_tensor_buft_override*, unsigned long*, unsigned int, ggml_log_level)::ngl_t, std::allocator<common_params_fit_impl(char const*, llama_model_params*, llama_context_params*, float*, llama_model_tensor_buft_override*, unsigned long*, unsigned int, ggml_log_level)::ngl_t> > const&, std::vector<ggml_backend_buffer_type*, std::allocator<ggml_backend_buffer_type*> > const&)#1}::operator()(char const*, std::vector<common_params_fit_impl(char const*, llama_model_params*, llama_context_params*, float*, llama_model_tensor_buft_override*, unsigned long*, unsigned int, ggml_log_level)::ngl_t, std::allocator<common_params_fit_impl(char const*, llama_model_params*, llama_context_params*, float*, llama_model_tensor_buft_override*, unsigned long*, unsigned int, ggml_log_level)::ngl_t> > const&, std::vector<ggml_backend_buffer_type*, std::allocator<ggml_backend_buffer_type*> > const&) const [clone .constprop.0] ()
       from /home/eapache/src/llama.cpp/build/bin/libllama-common.so.0
    #13 0x000079b3b6645cc6 in common_params_fit_impl(char const*, llama_model_params*, llama_context_params*, float*, llama_model_tensor_buft_override*, unsigned long*, unsigned int, ggml_log_level) () from /home/eapache/src/llama.cpp/build/bin/libllama-common.so.0
    #14 0x000079b3b6648532 in common_fit_params(char const*, llama_model_params*, llama_context_params*, float*, llama_model_tensor_buft_override*, unsigned long*, unsigned int, ggml_log_level) () from /home/eapache/src/llama.cpp/build/bin/libllama-common.so.0
    #15 0x000079b3b6615f57 in common_init_result::common_init_result(common_params&, bool) () from /home/eapache/src/llama.cpp/build/bin/libllama-common.so.0
    #16 0x000079b3b6617193 in common_init_from_params(common_params&, bool) () from /home/eapache/src/llama.cpp/build/bin/libllama-common.so.0
    #17 0x000079b3b6bbcdaf in server_context_impl::load_model(common_params&) () from /home/eapache/src/llama.cpp/build/bin/libllama-server-impl.so
    #18 0x000079b3b6af2817 in llama_server(common_params&, int, char**) () from /home/eapache/src/llama.cpp/build/bin/libllama-server-impl.so
    
  2. eapache commented on Jul 17, 2026

    @eapache
    ContributorAuthor

    Building off of b2dd28a does not have this problem - this is almost certainly a regression from #25585 cc @am17an

    edit: confirmed, reverting just 0dc74e3 (the merge of that PR) makes it work again, although of course much more slowly. And without an OOM/alloc failure, so maybe my memory pressure guess was wrong.

  3. eapache commented on Jul 17, 2026

    @eapache
    ContributorAuthor

    Full logs (with -v) of reproduction
    out.log

  4. ggerganov commented on Jul 17, 2026

    @ggerganov
    Member

    Please attach logs with env GGML_SCHED_DEBUG=2 too.

  5. eapache commented on Jul 17, 2026

    @eapache
    ContributorAuthor

    out.log.gz

    With GGML_SCHED_DEBUG=2 - gzipped as they are 65MB raw.

  6. eapache commented on Jul 17, 2026

    @eapache
    ContributorAuthor

    At the suggestion of chatgpt: running with --no-op-offload sidesteps the bug on master.

  7. ggerganov commented on Jul 17, 2026

    @ggerganov
    Member

    Something seems to be forcing the flash attention and the HC ops to the device backend even for the CPU layers:

    0.01.781.553 D node # 32 (      ROPE):              kv_pe-0 (   0K) [  CPU         ] use=1,c=1:0.01.781.554 D      kv_norm-0 (view) (   0K) [  CPU         ]0.01.781.554 D               leaf_11 (   0K) [  CPU         ]0.01.781.554 D 
    0.01.781.554 D node # 33 (    CONCAT):                 kv-0 (   2K) [  CPU         ] use=1,c=1:0.01.781.554 D      kv_norm-0 (view) (   1K) [  CPU         ]0.01.781.554 D               kv_pe-0 (   0K) [  CPU         ]0.01.781.554 D 
    0.01.781.554 D node # 35 (  SET_ROWS):    cache_k_l0 (view) ( 768K) [  CPU         ] use=0,c=1:0.01.781.555 D           kv-0 (view) (   2K) [  CPU         ]0.01.781.555 D               leaf_14 (   0K) [  CPU         ]0.01.781.555 D            cache_k_l0 ( 768K) [  CPU         ]0.01.781.555 D 
    0.01.781.555 D 
    ## SPLIT #1: CUDA0 # 7 inputs0.01.781.555 D : 0.01.781.555 D [q-0 (view) (permuted) ( 128K)] 0.01.781.556 D [cache_k_l0 (view) (permuted) ( 768K)] 0.01.781.556 D [cache_k_l0 (view) (permuted) ( 768K)] 0.01.781.556 D [attn_inp_kq_mask (   1K)] 0.01.781.556 D [blk.0.attn_sinks.weight (   0K)] 0.01.781.556 D [leaf_11 (   0K)] 0.01.781.556 D [blk.0.attn_output_a.weight (reshaped) (  34M)] 0.01.781.556 D 
    0.01.781.557 D node # 41 (FLASH_ATTN):              node_41 ( 128K) [CUDA0         ] use=1,c=1:0.01.781.557 D  CUDA0#q-0 (view) (pe ( 128K) [ NULL         ]0.01.781.557 D  CUDA0#cache_k_l0 (vi ( 768K) [ NULL         ]0.01.781.557 D  CUDA0#cache_k_l0 (vi ( 768K) [ NULL         ]0.01.781.557 D  CUDA0#attn_inp_kq_ma (   1K) [ NULL         ]0.01.781.557 D  CUDA0#blk.0.attn_sin (   0K) [ NULL         ]0.01.781.557 D 
    0.01.781.558 D node # 47 ( ROPE_BACK):              node_47 (  16K) [CUDA0         ] use=1,c=1:0.01.781.558 D  attn_raw-0 (reshaped ( 126K) [CUDA0         ]0.01.781.558 D       CUDA0#leaf_11#0 (   0K) [ NULL         ]0.01.781.558 D 
    0.01.781.558 D node # 48 (    CONCAT):        attn_derope-0 ( 128K) [CUDA0         ] use=1,c=1:0.01.781.558 D  attn_raw-0 (reshaped ( 127K) [CUDA0         ]0.01.781.559 D               node_47 (  16K) [CUDA0         ]0.01.781.559 D 
    0.01.781.559 D node # 51 (   MUL_MAT):          attn_wo_a-0 (  32K) [CUDA0         ] use=1,c=1:0.01.781.559 D  CUDA0#blk.0.attn_out (  34M) [ NULL         ]0.01.781.560 D  attn_derope-0 (resha ( 128K) [CUDA0         ]0.01.781.560 D 
    0.01.781.560 D node # 53 (      CONT): attn_wo_a-0 (permute (  32K) [CUDA0         ] use=1,c=1:0.01.781.560 D  attn_wo_a-0 (permute (  32K) [CUDA0         ]0.01.781.560 D 
    0.01.781.560 D 
    ## SPLIT #2: CPU # 1 inputs0.01.781.560 D : 0.01.781.560 D [attn_wo_a-0 (permuted) (cont) (  32K)] 0.01.781.560 D 
    0.01.781.561 D node # 54 (   MUL_MAT):           attn_out-0 (  16K) [  CPU         ] use=1,c=1:0.01.781.561 D  blk.0.attn_output_b. (  34M) [  CPU         ]0.01.781.561 D  CPU#attn_wo_a-0 (per (  32K) [ NULL         ]0.01.781.561 D 
    0.01.781.561 D node # 57 (       MUL):              node_57 (   0K) [  CPU         ] use=1,c=1:0.01.781.562 D     hc_mixes-0 (view) (   0K) [  CPU         ]0.01.781.562 D  blk.0.hc_attn_scale. (   0K) [  CPU         ]0.01.781.562 D 
    0.01.781.562 D node # 59 (       ADD):              node_59 (   0K) [  CPU         ] use=1,c=1:0.01.781.562 D               node_57 (   0K) [  CPU         ]0.01.781.562 D  blk.0.hc_attn_base.w (   0K) [  CPU         ]0.01.781.562 D 
    0.01.781.562 D node # 60 (   SIGMOID):              node_60 (   0K) [  CPU         ] use=1,c=1:0.01.781.563 D               node_59 (   0K) [  CPU         ]0.01.781.563 D 
    
    ...
    
    0.01.797.841 W resolve_fused_ops: layer 0 is assigned to device CPU but Flash Attention is assigned to device CUDA0 (usually due to missing support)
    0.01.797.841 W resolve_fused_ops: Flash Attention not supported, set to disabled
    

    Not sure this is correct - should be traced why it happens.

  8. am17an commented on Jul 17, 2026

    @am17an
    Contributor

    It may the --fit process, not sure

  9. ggerganov commented on Jul 17, 2026

    @ggerganov
    Member

    It may the --fit process, not sure

    The fit process only tries to offload different number of layers. It shouldn't be the root cause. Likely you can reproduce the same problem with -ngl 39 -fit off.

    Most likely the CUDA backend decides to offload an op based on this logic:

    static int64_t get_op_batch_size(const ggml_tensor * op) {
    switch (op->op) {
    case GGML_OP_GET_ROWS:
    return 0;
    case GGML_OP_MUL_MAT:
    return op->ne[1];
    case GGML_OP_MUL_MAT_ID:
    case GGML_OP_ROPE:
    case GGML_OP_ROPE_BACK:
    return op->ne[2];
    default:
    return ggml_nrows(op);
    }
    }
    static bool ggml_backend_cuda_device_offload_op(ggml_backend_dev_t dev, const ggml_tensor * op) {
    ggml_backend_cuda_device_context * dev_ctx = (ggml_backend_cuda_device_context *) dev->context;
    return get_op_batch_size(op) >= dev_ctx->op_offload_min_batch_size;
    }

    Maybe ROPE_BACK? And from there the FA is also offloaded.


    Additionally, looking at the DSV4 graph, it is doing view operations with the weights. For example:

    ggml_tensor * oa = ggml_mul_mat(ctx0, ggml_reshape_3d(ctx0, layer.wo_a, layer.wo_a->ne[0], o_lora_rank, n_groups), out);

    ggml_tensor * scale_pre = dsv4_view_1d(ctx0, hc_scale, 1, 0);
    ggml_tensor * scale_post = dsv4_view_1d(ctx0, hc_scale, 1, 1);

    This does not play well with the "tensor info" logic here:

    // declare information about the model weight tensors:
    // - the layer in which the tensor is going to be used. this is needed in order to assign the correct buffer type for the weight
    // - the operator which is going to use the weight. this is needed to determine if the respective backend supports the operator
    //
    // for example, input layers are usually assigned to CPU/host buffer types
    //
    // a mismatch between the declared information and the actual layer/op in which the tensor is used can lead to sub-optimal
    // assignment of the buffer types and extra overhead during computation
    // example: https://github.com/ggml-org/llama.cpp/pull/17548
    //
    static const std::map<llm_tensor, llm_tensor_info> LLM_TENSOR_INFOS = {
    {LLM_TENSOR_TOKEN_EMBD, {LLM_TENSOR_LAYER_INPUT, GGML_OP_GET_ROWS}},
    {LLM_TENSOR_POS_EMBD, {LLM_TENSOR_LAYER_INPUT, GGML_OP_GET_ROWS}},

    Generally, a weight should be used directly as it is loaded, without reshaping or viewing it. I recommend to fix that for DSV4 or we will keep seeing such problems like this issue. The fix would require updating the convert process to shape the weights in the right dimensions and using them directly, as declared in the "tensor info" section.

    cc @fairydreaming for viz

  10. am17an commented on Jul 17, 2026

    @am17an
    Contributor

    Yes this was done originally to conform with the existing antirez GGUF IIRC

  11. ggerganov commented on Jul 17, 2026

    @ggerganov
    Member

    Yes, this is true for the wo_a tensor. But the HC tensors have the same problem.

  12. am17an commented on Jul 17, 2026

    @am17an
    Contributor

    HC tensors can be fixed on conversion, the wo_a weight I think we can still keep around?

  13. ggerganov commented on Jul 17, 2026

    @ggerganov
    Member

    I think #25832 should fix the current issue.

    HC tensors can be fixed on conversion, the wo_a weight I think we can still keep around?

    If we update the conversion, it's best to update all tensors. There is no reason to have the wo_a to be a 2D tensor in the model file if we always reshape it to 3D first.

  14. am17an commented on Jul 17, 2026

    @am17an
    Contributor

    The reason is simply to load those existing GGUFs, but we can have if/else for this case?

  15. ggerganov commented on Jul 17, 2026

    @ggerganov
    Member

    Yes, we can have if/else to support both. But my point was that if we change the HC tensors conversion (as you suggested), there is no reason not to change the wo_a tensor conversion too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions