@@ -170,16 +170,64 @@ static void dflash_log_backend_layout(
170170
171171static ggml_backend_t dflash_backend_for_dev (
172172 const std::vector<ggml_backend_ptr> & backends,
173- ggml_backend_dev_t want_dev) {
173+ ggml_backend_dev_t want_dev,
174+ bool allow_meta = false ) {
174175 for (const auto & backend : backends) {
175176 auto * dev = ggml_backend_get_device (backend.get ());
176- if (dev == want_dev && dflash_backend_dev_is_gpu (dev)) {
177+ if (dev == want_dev && (dflash_backend_dev_is_gpu (dev) ||
178+ (allow_meta && ggml_backend_dev_is_meta (dev)))) {
177179 return backend.get ();
178180 }
179181 }
180182 return nullptr ;
181183}
182184
185+ struct dflash_capture_backend {
186+ ggml_backend_t backend = nullptr ;
187+ ggml_backend_dev_t dev = nullptr ;
188+ bool from_meta = false ;
189+ };
190+
191+ static dflash_capture_backend dflash_capture_backend_for_layer (
192+ const std::vector<ggml_backend_ptr> & backends,
193+ ggml_backend_dev_t layer_dev) {
194+ dflash_capture_backend result;
195+
196+ result.backend = dflash_backend_for_dev (backends, layer_dev, layer_dev && ggml_backend_dev_is_meta (layer_dev));
197+ if (result.backend ) {
198+ result.dev = layer_dev;
199+ result.from_meta = layer_dev && ggml_backend_dev_is_meta (layer_dev);
200+ return result;
201+ }
202+
203+ if (!layer_dev || !ggml_backend_dev_is_meta (layer_dev)) {
204+ return result;
205+ }
206+
207+ const size_t n_devs = ggml_backend_meta_dev_n_devs (layer_dev);
208+ for (size_t i = 0 ; i < n_devs; ++i) {
209+ ggml_backend_dev_t simple_dev = ggml_backend_meta_dev_simple_dev (layer_dev, i);
210+ result.backend = dflash_backend_for_dev (backends, simple_dev);
211+ if (result.backend ) {
212+ result.dev = simple_dev;
213+ result.from_meta = true ;
214+ return result;
215+ }
216+ }
217+
218+ return result;
219+ }
220+
221+ static bool dflash_tensor_buffer_is_meta (const ggml_tensor * tensor) {
222+ if (!tensor || !tensor->buffer ) {
223+ return false ;
224+ }
225+
226+ ggml_backend_buffer_type_t buft = ggml_backend_buffer_get_type (tensor->buffer );
227+ ggml_backend_dev_t dev = buft ? ggml_backend_buft_get_device (buft) : nullptr ;
228+ return ggml_backend_dev_is_meta (dev);
229+ }
230+
183231static void dflash_capture_add_wait_backend (
184232 dflash_capture_data & cap,
185233 ggml_backend_t backend,
@@ -2161,8 +2209,8 @@ void llama_context::allocate_tape_gpu(int n_slots, int max_tokens) {
21612209 for (int li = 0 ; li < n_rec; ++li) {
21622210 const int il = rec_ids[li];
21632211 ggml_backend_dev_t layer_dev = model.dev_layer (il);
2164- ggml_backend_t layer_backend = dflash_backend_for_dev (backends, layer_dev);
2165- if (!layer_backend ) {
2212+ const dflash_capture_backend capture_backend = dflash_capture_backend_for_layer (backends, layer_dev);
2213+ if (!capture_backend. backend ) {
21662214 LLAMA_LOG_WARN (" %s: no GPU backend for recurrent layer %d device %s; falling back to CPU tape\n " ,
21672215 __func__, il, layer_dev ? ggml_backend_dev_name (layer_dev) : " <null>" );
21682216 dflash_capture->tapes .clear ();
@@ -2193,29 +2241,29 @@ void llama_context::allocate_tape_gpu(int n_slots, int max_tokens) {
21932241 tl.qkv = ggml_new_tensor_2d (tape_ctx, GGML_TYPE_F32 , conv_ch, (int64_t )max_tokens);
21942242
21952243 tl.ctx = tape_ctx;
2196- tl.dev = layer_dev ;
2197- tl.buf = ggml_backend_alloc_ctx_tensors (tape_ctx, layer_backend );
2244+ tl.dev = capture_backend. dev ;
2245+ tl.buf = ggml_backend_alloc_ctx_tensors (tape_ctx, capture_backend. backend );
21982246
21992247 if (!tl.buf ) {
22002248 LLAMA_LOG_WARN (" %s: failed to allocate GPU tape buffer for slot %d layer %d device %s, falling back to CPU tape\n " ,
2201- __func__, slot, il, layer_dev ? ggml_backend_dev_name (layer_dev ) : " <null>" );
2249+ __func__, slot, il, capture_backend. dev ? ggml_backend_dev_name (capture_backend. dev ) : " <null>" );
22022250 dflash_capture->tapes .clear ();
22032251 return ;
22042252 }
22052253
2206- dflash_capture_add_wait_backend (*dflash_capture, layer_backend , ggml_backend_dev_backend_reg (layer_dev ));
2254+ dflash_capture_add_wait_backend (*dflash_capture, capture_backend. backend , ggml_backend_dev_backend_reg (capture_backend. dev ));
22072255 total_size += ggml_backend_buffer_get_size (tl.buf );
22082256
22092257 bool found = false ;
22102258 for (auto & dc : dev_counts) {
2211- if (dc.dev == layer_dev ) {
2259+ if (dc.dev == capture_backend. dev ) {
22122260 ++dc.count ;
22132261 found = true ;
22142262 break ;
22152263 }
22162264 }
22172265 if (!found) {
2218- dev_counts.push_back ({ layer_dev , 1 });
2266+ dev_counts.push_back ({ capture_backend. dev , 1 });
22192267 }
22202268 }
22212269
@@ -2275,8 +2323,8 @@ void llama_context::allocate_hidden_gpu(int n_slots, int max_tokens) {
22752323 for (int i = 0 ; i < n_layers; ++i) {
22762324 const int il = dflash_capture->layer_ids [i];
22772325 ggml_backend_dev_t layer_dev = model.dev_layer (il);
2278- ggml_backend_t layer_backend = dflash_backend_for_dev (backends, layer_dev);
2279- if (!layer_backend ) {
2326+ const dflash_capture_backend capture_backend = dflash_capture_backend_for_layer (backends, layer_dev);
2327+ if (!capture_backend. backend ) {
22802328 LLAMA_LOG_WARN (" %s: no GPU backend for hidden layer %d device %s; using callback hidden fallback\n " ,
22812329 __func__, il, layer_dev ? ggml_backend_dev_name (layer_dev) : " <null>" );
22822330 dflash_capture->hidden_gpu .clear ();
@@ -2296,15 +2344,15 @@ void llama_context::allocate_hidden_gpu(int n_slots, int max_tokens) {
22962344
22972345 hidden->layers [i] = ggml_new_tensor_2d (hidden_ctx, GGML_TYPE_F32 , n_embd, (int64_t ) max_tokens);
22982346
2299- ggml_backend_buffer_t buf = ggml_backend_alloc_ctx_tensors (hidden_ctx, layer_backend );
2347+ ggml_backend_buffer_t buf = ggml_backend_alloc_ctx_tensors (hidden_ctx, capture_backend. backend );
23002348 if (!buf) {
23012349 LLAMA_LOG_WARN (" %s: failed to allocate GPU hidden buffer for slot %d layer %d; using callback hidden fallback\n " ,
23022350 __func__, slot, il);
23032351 dflash_capture->hidden_gpu .clear ();
23042352 return ;
23052353 }
23062354 hidden->bufs .push_back (buf);
2307- dflash_capture_add_wait_backend (*dflash_capture, layer_backend , ggml_backend_dev_backend_reg (layer_dev ));
2355+ dflash_capture_add_wait_backend (*dflash_capture, capture_backend. backend , ggml_backend_dev_backend_reg (capture_backend. dev ));
23082356 total_size += ggml_backend_buffer_get_size (buf);
23092357 }
23102358
@@ -2361,8 +2409,8 @@ bool llama_context::allocate_prefill_gpu(int n_slots, int max_tokens) {
23612409 for (int i = 0 ; i < n_layers; ++i) {
23622410 const int il = dflash_capture->layer_ids [i];
23632411 ggml_backend_dev_t layer_dev = model.dev_layer (il);
2364- ggml_backend_t layer_backend = dflash_backend_for_dev (backends, layer_dev);
2365- if (!layer_backend ) {
2412+ const dflash_capture_backend capture_backend = dflash_capture_backend_for_layer (backends, layer_dev);
2413+ if (!capture_backend. backend ) {
23662414 LLAMA_LOG_WARN (" %s: no GPU backend for prefill layer %d device %s; using callback fallback\n " ,
23672415 __func__, il, layer_dev ? ggml_backend_dev_name (layer_dev) : " <null>" );
23682416 dflash_capture->prefill_gpu .clear ();
@@ -2384,7 +2432,7 @@ bool llama_context::allocate_prefill_gpu(int n_slots, int max_tokens) {
23842432
23852433 hidden->layers [i] = ggml_new_tensor_2d (hidden_ctx, GGML_TYPE_F32 , n_embd, (int64_t ) max_tokens);
23862434
2387- ggml_backend_buffer_t buf = ggml_backend_alloc_ctx_tensors (hidden_ctx, layer_backend );
2435+ ggml_backend_buffer_t buf = ggml_backend_alloc_ctx_tensors (hidden_ctx, capture_backend. backend );
23882436 if (!buf) {
23892437 LLAMA_LOG_WARN (" %s: failed to allocate prefill GPU buffer for slot %d layer %d; using callback fallback\n " ,
23902438 __func__, slot, il);
@@ -2393,7 +2441,7 @@ bool llama_context::allocate_prefill_gpu(int n_slots, int max_tokens) {
23932441 return false ;
23942442 }
23952443 hidden->bufs .push_back (buf);
2396- dflash_capture_add_wait_backend (*dflash_capture, layer_backend , ggml_backend_dev_backend_reg (layer_dev ));
2444+ dflash_capture_add_wait_backend (*dflash_capture, capture_backend. backend , ggml_backend_dev_backend_reg (capture_backend. dev ));
23972445 total_size += ggml_backend_buffer_get_size (buf);
23982446 }
23992447
@@ -8792,7 +8840,8 @@ bool llama_context::cross_ring_gpu_write_hidden(void * handle, int layer, int ri
87928840 }
87938841
87948842 auto * tensor = hgpu->layers [layer];
8795- if (!tensor || !tensor->data ) {
8843+ const bool tensor_is_meta = dflash_tensor_buffer_is_meta (tensor);
8844+ if (!tensor || !tensor->buffer || (!tensor_is_meta && !tensor->data )) {
87968845 return false ;
87978846 }
87988847 if (!dflash_gpu_hidden_span_in_bounds (tensor, src_offset, n_tokens, n_embd, __func__)) {
@@ -8801,15 +8850,17 @@ bool llama_context::cross_ring_gpu_write_hidden(void * handle, int layer, int ri
88018850
88028851 auto * h = (dflash_cross_ring_handle *)handle;
88038852 const size_t src_offset_bytes = (size_t ) src_offset * (size_t ) n_embd * sizeof (float );
8804- const void * src = (const char *) tensor->data + src_offset_bytes;
8805- if (h->fn_write_d2d (h->gpu_ring , layer, ring_pos, src, n_tokens, n_embd)) {
8806- return true ;
8853+ if (!tensor_is_meta) {
8854+ const void * src = (const char *) tensor->data + src_offset_bytes;
8855+ if (h->fn_write_d2d (h->gpu_ring , layer, ring_pos, src, n_tokens, n_embd)) {
8856+ return true ;
8857+ }
88078858 }
88088859
88098860 static bool warned_d2h_fallback = false ;
88108861 if (!warned_d2h_fallback) {
8811- LLAMA_LOG_WARN (" %s: GPU hidden D2D ring write unavailable; falling back to GPU readback + H2D ring upload\n " ,
8812- __func__);
8862+ LLAMA_LOG_WARN (" %s: GPU hidden D2D ring write unavailable%s ; falling back to backend readback + H2D ring upload\n " ,
8863+ __func__, tensor_is_meta ? " for Meta capture tensor " : " " );
88138864 warned_d2h_fallback = true ;
88148865 }
88158866
@@ -8843,7 +8894,8 @@ bool llama_context::prefill_gpu_write_hidden(void * handle, int slot, int layer,
88438894 }
88448895
88458896 auto * tensor = pgpu->layers [layer];
8846- if (!tensor || !tensor->data ) {
8897+ const bool tensor_is_meta = dflash_tensor_buffer_is_meta (tensor);
8898+ if (!tensor || !tensor->buffer || (!tensor_is_meta && !tensor->data )) {
88478899 return false ;
88488900 }
88498901 if (!dflash_gpu_hidden_span_in_bounds (tensor, src_offset, n_tokens, n_embd, __func__)) {
@@ -8852,15 +8904,17 @@ bool llama_context::prefill_gpu_write_hidden(void * handle, int slot, int layer,
88528904
88538905 auto * h = (dflash_cross_ring_handle *)handle;
88548906 const size_t src_offset_bytes = (size_t ) src_offset * (size_t ) n_embd * sizeof (float );
8855- const void * src = (const char *) tensor->data + src_offset_bytes;
8856- if (h->fn_write_d2d (h->gpu_ring , layer, ring_pos, src, n_tokens, n_embd)) {
8857- return true ;
8907+ if (!tensor_is_meta) {
8908+ const void * src = (const char *) tensor->data + src_offset_bytes;
8909+ if (h->fn_write_d2d (h->gpu_ring , layer, ring_pos, src, n_tokens, n_embd)) {
8910+ return true ;
8911+ }
88588912 }
88598913
88608914 static bool warned_prefill_d2h_fallback = false ;
88618915 if (!warned_prefill_d2h_fallback) {
8862- LLAMA_LOG_WARN (" %s: prefill GPU D2D ring write unavailable; falling back to GPU readback + H2D ring upload\n " ,
8863- __func__);
8916+ LLAMA_LOG_WARN (" %s: prefill GPU D2D ring write unavailable%s ; falling back to backend readback + H2D ring upload\n " ,
8917+ __func__, tensor_is_meta ? " for Meta capture tensor " : " " );
88648918 warned_prefill_d2h_fallback = true ;
88658919 }
88668920
0 commit comments