MCPcopy Create free account
hub / github.com/cactus-compute/cactus / prefill_npu

Method prefill_npu

cactus/engine/engine_model.cpp:925–997  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

923}
924
925void Model::prefill_npu(const std::vector<uint32_t>& tokens) {
926 if (!npu_prefill_ || !npu_prefill_->is_available()) {
927 throw std::runtime_error("NPU prefill not available");
928 }
929
930 const int chunk_size = npu_prefill_->get_chunk_size();
931 const int hidden_dim = npu_prefill_->get_hidden_dim();
932 const int num_layers = npu_prefill_->get_num_layers();
933 const int fallback_num_kv_heads = npu_prefill_->get_num_kv_heads();
934 const int fallback_head_dim = npu_prefill_->get_head_dim();
935
936 const std::vector<size_t> layer_dims = get_kv_layer_dims();
937 const std::vector<size_t> layer_heads = get_kv_layer_heads();
938 const int layers_to_update = std::min<int>(num_layers, static_cast<int>(config_.num_layers));
939
940 std::vector<__fp16> all_embeddings = get_token_embeddings(tokens);
941 if (all_embeddings.empty()) {
942 throw std::runtime_error("Failed to get token embeddings for NPU prefill");
943 }
944
945 if (Config::is_gemma_family(config_.model_type)) {
946 float scale = std::sqrt(static_cast<float>(hidden_dim));
947 for (size_t i = 0; i < all_embeddings.size(); i++) {
948 all_embeddings[i] = __fp16(static_cast<float>(all_embeddings[i]) * scale);
949 }
950 }
951
952 size_t num_tokens = tokens.size();
953 size_t num_chunks = (num_tokens + chunk_size - 1) / chunk_size;
954
955 for (size_t c = 0; c < num_chunks; c++) {
956 size_t start = c * chunk_size;
957 size_t actual_tokens = std::min(static_cast<size_t>(chunk_size), num_tokens - start);
958
959 std::vector<__fp16> chunk_embeddings(chunk_size * hidden_dim, __fp16(0));
960 std::copy(all_embeddings.begin() + start * hidden_dim,
961 all_embeddings.begin() + (start + actual_tokens) * hidden_dim,
962 chunk_embeddings.begin());
963
964 int position_offset = static_cast<int>(start);
965
966 npu::NPUPrefillDirectResult direct_result = npu_prefill_->prefill_chunk_direct(chunk_embeddings, position_offset);
967
968 if (direct_result.valid) {
969 for (int layer_idx = 0; layer_idx < layers_to_update; layer_idx++) {
970 const auto& k_ref = direct_result.k_caches[layer_idx];
971 const auto& v_ref = direct_result.v_caches[layer_idx];
972
973 if (k_ref.data && v_ref.data) {
974 size_t layer_kv_heads = layer_idx < static_cast<int>(layer_heads.size())
975 ? layer_heads[layer_idx]
976 : static_cast<size_t>(fallback_num_kv_heads);
977 size_t layer_head_dim = layer_idx < static_cast<int>(layer_dims.size())
978 ? layer_dims[layer_idx]
979 : static_cast<size_t>(fallback_head_dim);
980
981 size_t expected = static_cast<size_t>(chunk_size) * layer_kv_heads * layer_head_dim;
982 if (expected > 0 && (k_ref.count < expected || v_ref.count < expected)) {

Callers

nothing calls this directly

Calls 9

get_chunk_sizeMethod · 0.80
get_hidden_dimMethod · 0.80
get_num_layersMethod · 0.80
get_num_kv_headsMethod · 0.80
get_head_dimMethod · 0.80
sizeMethod · 0.80
prefill_chunk_directMethod · 0.80
update_from_npuMethod · 0.80
is_availableMethod · 0.45

Tested by

no test coverage detected