deepinfer-commit
deepinfer/csrc/engine/scheduler.hpp · a679bb8 · L899–1003 · 固定 commit 上游
这是固定版本源码的只读摘录;可在线阅读,也可通过上游链接查看原文件。
899 for (ssize_t i = 0; i < num_output_tokens; i++) {
900 auto &seq = *scheduler_outputs.scheduled_seqs[i];
901 auto &seq_ptr = scheduler_outputs.scheduled_seqs[i];
902
903 seq.schedule.finish_inflight_step();
904
905 // seq is already aborted
906 if (seq.is_finished()) {
907 release_mtp_info_slot(seq);
908 pushed_tokens_before_finish.push_back(0);
909 if (scheduler_outputs.prompt_run) {
910 running.push_back(seq_ptr);
911 }
912 if (has_accepted_tokens)
913 flat_offset += scheduler_outputs.seqlens_q[i];
914 continue;
915 }
916
917 // ZOS 异步:本步尚在途时就被 _preempt 抢占重算的 seq(只在 decode 步出现——prompt 步的
918 // 在途 seq 不在 running 里,不会成为抢占目标)。_preempt 已复位其计数并放回 waiting 队头,
919 // 本步输出作废:跳过全部记账,避免重复入队与 cache.num_tokens 的错误推进。
920 if (!scheduler_outputs.prompt_run && seq.schedule.status == SequenceStatus::WAITING) {
921 pushed_tokens_before_finish.push_back(0);
922 if (has_accepted_tokens)
923 flat_offset += scheduler_outputs.seqlens_q[i];
924 continue;
925 }
926
927 seq.cache.advance_optimistically(scheduler_outputs.seqlens_q[i]);
928 if (so_status_bool)
929 seq.structured_output.status = so_status[i].cast<int>();
930
931 // 乐观推进后 cache.num_tokens 的不变式(input.tokens 只含已提交 token,不含 draft,契约见其声明处;
932 // 在途被抢占的 seq 已在上面跳过):
933 // prompt 步:seqlen_q 只覆盖 prompt 本身,推进后 <= len,等于 len 说明本 seq 的 prefill 已完成;
934 // decode 步:seqlen_q = 1 + 参与验证的 draft 数,推进后其值落在 [len, len + nextn] 内,
935 // 多算的部分随后按实际接受的 token 数(token_cnt)回填修正。
936 TORCH_CHECK(seq.cache.num_tokens <= seq.input.tokens.get_len() + seq.get_nextn_len());
937 bool prefill_finish_or_is_decode = (seq.cache.num_tokens >= seq.input.tokens.get_len());
938 TORCH_CHECK(scheduler_outputs.prompt_run || prefill_finish_or_is_decode, "decode 步推进后必然 >= len,不应该:",
939 seq.cache.num_tokens, " < ", seq.input.tokens.get_len());
940 if (prefill_finish_or_is_decode) {
941 if (engine_type == EngineType::NORMAL) { /// prefill_engine won't change status
942 /// because it will be transferred to
943 /// complete_engine
944 TORCH_CHECK(seq_ptr->schedule.status == SequenceStatus::RUNNING,
945 SPRINT_VARS("`seq_ptr->schedule.status` should be RUNNING. "
946 "`seq_ptr->schedule.status` is updated in `_allocate`. "
947 "Check if the `allocate` is called at the end of "
948 "the prefill phase. Got",
949 int(seq_ptr->schedule.status)));
950 }
951 if (scheduler_outputs.prompt_run) {
952 running.push_back(seq_ptr);
953 }
954
955 // 提取本步验证通过的 draft tokens(flat 布局见 accepted_token_ids 参数注释)
956 accepted_token_ids_vec.clear();
957 if (has_accepted_tokens) {
958 int num_draft_i = scheduler_outputs.seqlens_q[i] - 1;
959 for (int j = 0; j < num_draft_i; j++) {
960 int token_id = accepted_token_ids_ptr[flat_offset + j];
961 if (token_id != -1) {
962 accepted_token_ids_vec.push_back(token_id);
963 } else
964 break;
965 }
966 }
967 seq.mtp.accepted_tokens = accepted_token_ids_vec;
968
969 token_ids = accepted_token_ids_vec;
970 seq.mtp.last_output_token = output_token_ids_data[i];
971 token_ids.push_back(seq.mtp.last_output_token);
972
973 int token_cnt = 0;
974 // 判死看账本 structured_output.status 而非当步上报:sampler 对批内无活跃 SO 的步返回 None,
975 // 只认上报会让账本已是 -1 的 seq(如 PE 判死后迁到 CE 的副本)无约束自由生成
976 if (seq.structured_output.status == -1) {
977 seq.schedule.status = SequenceStatus::FINISHED_SO_FAILED;
978 seq.append_token_id(0);
979 seq.append_compressed_token_id(0);
980 token_cnt++;
981 } else {
982 for (auto token_id : token_ids) {
983 seq.append_token_id(token_id);
984 seq.append_compressed_token_id(map_engram(token_id));
985 token_cnt++;
986 _check_stop(seq);
987 if (seq.is_finished()) {
988 break;
989 }
990 }
991 }
992 if (seq.is_finished()) {
993 release_mtp_info_slot(seq);
994 }
995 pushed_tokens_before_finish.push_back(token_cnt);
996
997 if (!scheduler_outputs.prompt_run) {
998 // decode:把 cache.num_tokens 从乐观推进值回填为实际接受数(未被接受的 draft 不占 KV)
999 seq.cache.commit_processed_tokens(token_cnt);
1000 }
1001 TORCH_CHECK(seq.cache.num_tokens <= seq.input.tokens.get_len(),
1002 "assert seq.cache.num_tokens <= seq.input.tokens.get_len(), seq.cache.num_tokens:", seq.cache.num_tokens,
1003 " seq.input.tokens.get_len():", seq.input.tokens.get_len());