perf(cuda): reduce redundant per-token synchronizations#22
Closed
hai-pilgrim wants to merge 12 commits into
Closed
perf(cuda): reduce redundant per-token synchronizations#22hai-pilgrim wants to merge 12 commits into
hai-pilgrim wants to merge 12 commits into
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Register Qwen2_5OmniThinkerForConditionalGeneration architecture for text and mmproj GGUF conversion. Handle config structure difference where the Thinker-only variant has vision/audio configs at the top level. Add pooling type detection for embedding use cases. Fix audio tensor routing to base MmprojModel class. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…eiervang-technologies#6) * docs: add ht-fork documentation, branding, and discussion links Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * convert: support LoRA conversion for MLA kv_b_proj Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: add fork sync automation * feat: add --remap-developer-role flag to translate developer→system Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: support LCO-Embedding-Omni (Qwen2.5 Omni Thinker) GGUF conversion Register Qwen2_5OmniThinkerForConditionalGeneration architecture for text and mmproj GGUF conversion. Handle config structure difference where the Thinker-only variant has vision/audio configs at the top level. Add pooling type detection for embedding use cases. Fix audio tensor routing to base MmprojModel class. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: add ht branch to flake8 lint workflow triggers * feat: welcome agentic contributions, remove upstream AI restrictions - Delete AGENTS.md (upstream's anti-AI contributor guidelines) - Replace restrictive AI Usage Policy with welcoming Agentic Contributions section - Update README to highlight fork's pragmatic stance on AI contributions Unlike upstream, we evaluate code by quality, not by how it was written. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…hnologies#8) * webui: add cancel button for in-progress model loading Allow users to cancel a model that is stuck loading or taking too long in the router mode model selector. The cancel button appears next to the loading spinner in both the model selector dropdown/sheet trigger and within individual model option rows. Uses the existing /models/unload endpoint which already supports unloading models in LOADING state. The frontend polling loop is interrupted via AbortController to prevent stale error toasts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * webui: add cancelling state indicator and fix cancel polling - Show orange "Cancelling" indicator with spinner while cancel is in progress - Poll until server confirms model is no longer in LOADING state before clearing the cancelling indicator - Guard against redundant unload calls on already-unloaded models - Keep loadingModelId alive during cancel so selector trigger shows the cancelling state correctly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(webui): color-coded spinners for model load/unload/cancel states - Loading: green spinner, clockwise - Unloading: red spinner, reverse direction with "Unloading" label - Cancelling: orange spinner, reverse direction - Track unloading state separately in models store Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(webui): address PR review feedback for cancel model loading - Remove duplicated cancel logic from ModelsSelector and ModelsSelectorSheet by deriving loading/cancelling state from the store (issue heiervang-technologies#1) - Fix race condition: no longer set isLoadingModel=false before cancel completes, preventing brief UI flash (issue heiervang-technologies#2) - Add MAX_CANCEL_POLL_ATTEMPTS (60) timeout to cancel polling loop to prevent infinite polling if server never transitions (issue heiervang-technologies#3) - Replace div cancel buttons with proper <button> elements for keyboard accessibility and screen reader support (issue heiervang-technologies#4) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…eiervang-technologies#10) - Rename all frontend references from "llama.cpp" to "ht-llama.cpp" - Dark mode: turquoise-tinted backgrounds, purple-tinted text - Light mode: inverted — turquoise backgrounds, purple text - Add reverse spin animation utility class Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…eiervang-technologies#14) Auto-discover LoRA adapters from the models directory by scanning GGUF metadata (general.type = "adapter") and match them to models by architecture. Adapters are loaded with --lora-init-without-apply so they start disabled and can be toggled on via the UI. Frontend adds a Popover-based LoRA dropdown in the chat action bar (next to model selector) with multi-select checkboxes and scale inputs. Includes "Show only matching" toggle to view all discovered adapters. Works in both MODEL and ROUTER mode. Backend changes: - Add GGUF metadata scanning for adapter classification (preset.cpp) - Auto-inject matching LoRA adapters into child process args (server-models.cpp) - Include discovered adapters in /v1/models response - Fix router proxy for /lora-adapters POST (array body fallback to query param) Frontend changes: - New LoraAdapters popover component with checkbox multi-select - LoRA service with router mode support (query param routing) - Reactive store with toggle, scale, change tracking, apply - Integration in ChatFormActions bar and chat completion requests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove unnecessary CUDA synchronization points that add latency without providing correctness benefits: 1. mul_mat_id: remove cudaStreamSynchronize after H2D async copy of sorted IDs buffer - the subsequent get_rows_cuda kernel runs on the same stream, so CUDA stream ordering already guarantees completion. 2. split_buffer_set_tensor: replace N redundant cudaStreamSynchronize calls (looped once per device count) with a single sync - all async H2D copies use the same cudaStreamPerThread. 3. split_buffer_get_tensor: same fix as above for D2H copies. These are scheduling-only changes with bit-exact output. Safe for multi-GPU (split buffer sync still waits for all copies) and single-GPU. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6 tasks
2189217 to
65d629d
Compare
6846da3 to
139f68e
Compare
|
Closing — head branch was deleted from remote. Reopen with a fresh branch if the work is still relevant. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Removes unnecessary CUDA synchronization points in the inference pipeline to reduce per-token latency. Inspired by upstream PR ggml-org#20793 which demonstrated measurable gains by reducing redundant syncs between async operations and graph execution.
All changes are scheduling-only — no computation changes, bit-exact output preserved.
Sync points changed
1.
ggml_cuda_mul_mat_id— remove stream sync after H2D copy (line ~2420)cudaMemcpyAsync(H2D) followed bycudaStreamSynchronize, thenget_rows_cudakernel on the same stream2.
ggml_backend_cuda_split_buffer_set_tensor— deduplicate sync loop (lines ~951-953)cudaStreamPerThread, a loop calledcudaStreamSynchronize(cudaStreamPerThread)once per device count — syncing the same stream N timescudaStreamSynchronize(cudaStreamPerThread)callcudaStreamPerThreadis a per-thread implicit stream. All copies are submitted to the same stream regardless of target device, so one sync drains the entire stream. The N-1 extra syncs were no-ops.3.
ggml_backend_cuda_split_buffer_get_tensor— deduplicate sync loop (lines ~990-992)cudaStreamSynchronize(cudaStreamPerThread)callWhat is NOT changed
cudaDeviceSynchronizeinggml_cuda_set_peer_access— this is a rare state-transition path for multi-GPU peer access that correctly requires device-wide synchronizationcudaStreamSynchronizeafter D2H copy ofids_hostinmul_mat_id(line ~2399) — host code reads the copied data immediately, so the sync is requiredset_tensor,get_tensor,memset_tensor,cpy_tensor,clear) — these are called from the generic backend API which expects synchronous completionCompatibility
Test plan
mul_mat_idpath)🤖 Generated with Claude Code