MCPcopy Create free account
hub / github.com/PABannier/sam3.cpp / edgetam_perceiver_forward

Function edgetam_perceiver_forward

sam3.cpp:5606–5858  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

5604}
5605
5606static bool edgetam_perceiver_forward(
5607 const sam3_model& model,
5608 const std::vector<float>& mem_features, // [64 * H * W]
5609 const std::vector<float>& mem_pos, // [64 * H * W]
5610 int H, int W,
5611 std::vector<float>& out_latents, // output: [512 * 64]
5612 std::vector<float>& out_pos) { // output: [512 * 64]
5613 auto t_start = std::chrono::high_resolution_clock::now();
5614
5615 const auto& perc = model.perceiver;
5616 const int D = 64;
5617 const int N_1d = 256; // number of 1D latent tokens
5618 const int N_2d = 256; // number of 2D latent tokens
5619 const int HW = H * W;
5620 const int n_layers = (int)perc.layers.size();
5621 const int nw = (int)sqrtf((float)N_2d); // 16 windows per spatial dim
5622 const int ws = H / nw; // window size (4 for H=64, 2 for H=32)
5623 const int ws2 = ws * ws; // tokens per window
5624
5625 fprintf(stderr, "%s: H=%d W=%d D=%d layers=%d 1d_tokens=%d 2d_tokens=%d ws=%d\n",
5626 __func__, H, W, D, n_layers, N_1d, N_2d, ws);
5627
5628 if (ws < 1 || H % ws != 0 || W % ws != 0) {
5629 fprintf(stderr, "%s: H=%d or W=%d not divisible by window_size=%d (nw=%d)\n",
5630 __func__, H, W, ws, nw);
5631 return false;
5632 }
5633 if (nw * nw != N_2d) {
5634 fprintf(stderr, "%s: expected %d 2D windows but got %d\n",
5635 __func__, N_2d, nw * nw);
5636 return false;
5637 }
5638
5639 // ── Read learnable latent tokens from model weights ─────────────────
5640 // latents_1d: ggml shape [64, 256] → ne[0]=64(D), ne[1]=256(N)
5641 std::vector<float> latents_1d_data(D * N_1d);
5642 sam3_read_f32(perc.latents_1d, latents_1d_data.data(), D * N_1d);
5643
5644 std::vector<float> latents_2d_data(D * N_2d);
5645 sam3_read_f32(perc.latents_2d, latents_2d_data.data(), D * N_2d);
5646
5647 // ── Prepare 2D windowed features on CPU ─────────────────────────────
5648 // mem_features layout: [D, H*W] (ggml: ne[0]=D, ne[1]=H*W, stored as
5649 // element (d, pos) at flat index d + pos*D where pos = w + h*W).
5650 // Actually, the features from the memory encoder have layout [D, W, H] in
5651 // ggml 4D, flattened to [D, H*W]. We need to interpret as a 2D spatial grid.
5652 // The input is already in [D, H*W] layout with spatial stride such that
5653 // pos = w + h * W.
5654
5655 // Window partition: [D, H*W] → [D, ws2, N_2d] i.e. [64, 16, 256]
5656 std::vector<float> feat_windowed(D * ws2 * N_2d);
5657 edgetam_window_partition_cpu(mem_features.data(), D, H, W, ws, feat_windowed.data());
5658
5659 // Reshape latents_2d for windowed processing: [D, N_2d] → [D, 1, N_2d]
5660 // Each window has exactly 1 latent token.
5661 // The latents_2d weight is [D, 256] = 256 latent tokens.
5662 // For 2D: batch=256 windows, each with 1 latent and 16 feature tokens.
5663 // Rearrange latents_2d from [D, 256] to [D, 1, 256] (batch dim = 256)

Callers 1

sam3_encode_memoryFunction · 0.85

Calls 6

sam3_read_f32Function · 0.85
sam3_layer_normFunction · 0.85
sam3_graph_computeFunction · 0.85
sam3_sinusoidal_pe_2dFunction · 0.85

Tested by

no test coverage detected