当前位置: 首页 > article >正文

MIT 6.824 lab3B/C

前言花两天把lab3B/C写了一下有了A的基础简单了不少。gitee地址放在末尾。一、3B/3C 前的整体认知1.1 3B 的目标Leader 接收Start(command)→ 追加到rf.logs→ 复制到多数派 → 推进commitIndex→ 通过applyChan交给状态机。1.2 3C 的目标把term / votedFor / logs做到“随时可重启且不违背承诺”同一任期不可能投两次票、日志不可能倒退。二、Part B日志复制Log Replication3B2.1 整体思路把 Raft 看成一条闭环流水线主要流程Start 写入 → AppendEntries 复制 → reply 反馈 → Leader 推进 commit → 心跳携带 LeaderCommit → 双端 applier 应用。客户端 → LeaderStartLeader → FollowersAppendEntries(entries, LeaderCommit)Followers → LeaderAppendEntriesReply(Success/Term)Leader更新 nextIndex/matchIndex → updateCommitIndex → 唤醒 applierFollowers更新 commitIndex → 唤醒 applier2.2 关键数据结构持久化状态3C 才真正持久化rf.term、rf.votedFor、rf.logs易失状态所有节点rf.commitIndex、rf.lastApplied易失状态Leader 专用rf.nextIndex[]、rf.matchIndex[]日志索引约定rf.logs[0]为占位条目term0, commandnil 不仅能够对日志进行更方便的访问在3D中这里放快照的最后一个日志信息第一条真实日志在 index1最后一条 index len(rf.logs)-12.3 Start(command)写这一段时建议按接口语义 并发点 返回值组织语义只有rf.stateLeader才能接收命令否则立即返回(-1, rf.term, false)写入追加LogEntry{Term: rf.term, Command: command}到rf.logs返回(index, term, true)触发复制两种常见方式- 触发一次广播推模式或- 等下一次心跳拉模式简单但可能慢func (rf *Raft) Start(command interface{}) (int, int, bool) { // Your code here (3B). rf.mu.Lock() if rf.Killed() { rf.mu.Unlock() return -1, -1, false } if rf.state ! Leader { rf.mu.Unlock() return -1, -1, false } term : rf.currentTerm index : rf.getLastIndex() 1 rf.logs append(rf.logs, LogEntry{Term: term, Command: command}) rf.persist() rf.mu.Unlock() //Leader 刚追加了一条日志立刻再推一轮 RPC不用干等下面 ticker 的 50ms 心跳周期复制会快一点 go rf.broadcastHeartbeat()//广播心跳 return index, term, true }2.4 AppendEntriesFollower 侧日志一致性检查与截断追加这一节建议用“检查顺序”写跟 Figure 2/论文一致最好对着一步步走term 检查args.Term rf.term直接拒绝回reply.Term rf.term退位与重置计时器收到合法 Leader 的 RPC →lastHeartBeatTime now必要时退回 Follower一致性检查用PrevLogIndex/PrevLogTerm验证日志前缀一致- 本地太短PrevLogIndex 超界→Successfalse- term 不匹配 →Successfalse截断并追加从PrevLogIndex1开始删除本地冲突后缀再追加Entries推进 commitIndexcommitIndex min(args.LeaderCommit, lastNewIndex)func (rf *Raft) AppendEntries(args *AppendEntriesArgs, reply *AppendEntriesReply) { rf.mu.Lock() defer rf.mu.Unlock() DPrintf([%d] AppendEntries from L%d term%d, my term%d state%d, rf.me, args.LeaderId, args.Term, rf.currentTerm, rf.state) reply.Success false reply.Term rf.currentTerm // 发现任期比自己小 if args.Term rf.currentTerm { DPrintf([%d] AppendEntries: 拒绝 term 更小 leader%d argsTerm%d myTerm%d, rf.me, args.LeaderId, args.Term, rf.currentTerm) return } // 发现更高任期或来自合法 Leader 的心跳 rf.lastHeartBeatTime time.Now() if args.Term rf.currentTerm { rf.currentTerm args.Term rf.votedFor -1 rf.persist() DPrintf([%d] step down to Follower due to AE term%d, rf.me, rf.currentTerm) } rf.state Follower //一致性检查 //日志长度不够 Follower 若还没有 PrevLogIndex 这一条才拒绝 if rf.getLastIndex() args.PrevLogIndex { // 3C reply.ConflictTerm -1 // 3C reply.ConflictIndex rf.getLastIndex() 1 // 3C return // 3C } //一致性检查PrevLogIndex 处的 Term 是否匹配 // 特别注意如果 PrevLogIndex 恰好在快照边界要用 LastIncludedIndex if args.PrevLogIndex rf.LastIncludedIndex { // 3C reply.ConflictTerm -1 // 3C reply.ConflictIndex rf.LastIncludedIndex 1 // 3C return // 3C } //PrevLogIndex处任期不匹配 if rf.getTermByIndex(args.PrevLogIndex) ! args.PrevLogTerm { // 3C reply.ConflictTerm rf.getTermByIndex(args.PrevLogIndex) // 3C idx : args.PrevLogIndex // 3C //从最新的日志位置开始向前找找到冲突任期的下标 //告诉leader这个下标是冲突任期的下标下一步继续找冲突位置若没有则进行同步 for idx rf.LastIncludedIndex rf.getTermByIndex(idx) reply.ConflictTerm { // 3C idx-- // 3C } reply.ConflictIndex idx 1 // 3C return // 3C } //追加日志 isChange : false // 3D for i, entry : range args.Entries { // 3D logicIdx : i args.PrevLogIndex 1 // 3D // 如果 logicIdx 已经落入快照范围跳过或者报错理论上不该发生 if logicIdx rf.LastIncludedIndex { // 3D continue // 3D } phyIdx : rf.getPhysicIdx(logicIdx) // 3D if phyIdx len(rf.logs) { // 3D //如果索引范围内已经有日志了检查任期 if rf.logs[phyIdx].Term ! entry.Term { // 3D //如果追加日志的位置的任期和leader日志的位置的任期不相等 //将idx下标前面的日志进行切片保留 rf.logs rf.logs[:phyIdx] // 3D rf.logs append(rf.logs, entry) // 3D isChange true // 3D } //如果任期一样说明这一段已经同步过了下一条 } else { // 3D //超出本地的日志长度直接追加 rf.logs append(rf.logs, entry) // 3D isChange true // 3D } } if isChange { // 3D rf.persist() // 3D } // 更新 CommitIndex须用「当前日志最后一条」与 LeaderCommit 取 min。 // 心跳时 len(Entries)0若仍用 PrevLogIndex0 会小于 getLastIndex()导致 commit 永远追不上 Leader。 if args.LeaderCommit rf.commitIndex { rf.commitIndex min(args.LeaderCommit, rf.getLastIndex()) rf.applyCond.Broadcast() } reply.Success true }2.5 Leader 侧复制nextIndex / matchIndex 维护这一部分主要分为两个小点发送时构造 args按 peer 单独算-prevIdx : nextIndex[i]-1-entries : logs[nextIndex[i]:] 将日志切片- 心跳就是entries为空但仍携带LeaderCommit收到回复时更新新增关键成员ConflictTerm 冲突任期/ ConflictIndex冲突任期索引-Successtrue更新matchIndex[i]、nextIndex[i]-Successfalse回退nextIndex[i]并重试-优化性能关键ConflictTerm / ConflictIndex让回退“整块跳过”func (rf *Raft) sendAppendEntries(server int, args *AppendEntriesArgs, reply *AppendEntriesReply) bool { ok : rf.peers[server].Call(Raft.AppendEntries, args, reply) if ok { rf.mu.Lock() defer rf.mu.Unlock() // 处理回复任期更新、调整 nextIndex 等 if reply.Term rf.currentTerm { rf.currentTerm reply.Term rf.state Follower rf.votedFor -1 rf.persist() return ok } // 2. 状态检查 if rf.state ! Leader || rf.currentTerm ! args.Term { return ok } // 3B 以后你会在这里处理日志同步的 reply.Success 为 false 的情况 // 如果追加日志成功 —— 对应论文 Leader 规则If successful, update matchIndex and nextIndex if reply.Success { newMathIdx : args.PrevLogIndex len(args.Entries) if newMathIdx rf.matchIndex[server] { rf.matchIndex[server] newMathIdx } rf.nextIndex[server] rf.matchIndex[server] 1 // 更新提交的日志 rf.updateCommitIndex() } else { // 如果失败根据 reply.ConflictIndex 实现快速跳转 —— 对应论文If AppendEntries fails because of log inconsistency, decrement nextIndex and retry if reply.ConflictTerm -1 { // 日志过短 rf.nextIndex[server] reply.ConflictIndex } else { flag : false for i : args.PrevLogIndex; i rf.LastIncludedIndex; i-- { if rf.getTermByIndex(i) reply.ConflictTerm { flag true rf.nextIndex[server] i 1 break } } if !flag { rf.nextIndex[server] reply.ConflictIndex } } } } return ok }2.6 updateCommitIndexLeader 如何合法推进提交这节写清楚 Figure 8 约束非常重要Leader 推进到某个 indexN的条件- 多数派matchIndex[i] N- 且logs[N].Term rf.term只用当前任期的日志推进提交间接提交旧任期日志推荐这样写从后往前找最大的 N更快注意边界len(logs)-1和len(logs)// 日志提交应用-leader专属matchIndex/commitIndex 均为逻辑索引 func (rf *Raft) updateCommitIndex() { if rf.state ! Leader { return } for i : rf.getLastIndex(); i rf.commitIndex; i-- { if rf.getTermByIndex(i) rf.currentTerm { cnt : 1 for j : range rf.peers { if j ! rf.me rf.matchIndex[j] i { cnt } } if cnt len(rf.peers)/21 { rf.commitIndex i rf.applyCond.Broadcast() break } } else if rf.getTermByIndex(i) rf.currentTerm { break } } }2.7 applier把已提交日志送到 applyChan不要持锁发 chan在这部分中需要特别注意的是不要用 sleep 轮询延迟大、测试反馈慢用 sync.CondcommitIndex 增加时Broadcast唤醒 applier锁内拷贝、锁外发送避免applyChan阻塞时卡死整个 Raft来看这个简短伪代码流程lock → 等待commitIndex lastAppliedcond.Wait计算要 apply 的区间拷贝 entriesunlock → 逐条向applyChan发送lock → 更新lastApplied→ unlock2.8 3B 典型 Bug 记录我按表格整理了一下常见的坑我基本都是踩过的问题分类具体描述Agreement FailedcommitIndex 没推进 / applier 没被唤醒就是集群明明已经达成一致了但commitIndex死活不涨或者涨了却没人去 apply。要么是 Leader 忘了给 Follower 发心跳要么是 Follower 收到了心跳却没更新自己的commitIndex再要么是applyLoop没被唤醒卡在 channel 上没人通知。too many RPCs心跳过频缺少节流每个日志条目都单独发一次 RPC或者心跳发得太快把网络打满。正确做法是用lastBroadcastTime做个节流比如 10ms 内只发一次心跳没必要每条日志都立刻广播。回退太慢未实现 conflict 优化日志冲突之后如果只靠nextIndex--一格格往回退遇到恶意日志会退几百次导致同步极慢。用论文里的conflict term 和 conflict index做快速回退一次性跳到冲突点性能好很多。死锁持锁发 chan / 持锁做重活最常见的是持有锁然后向 applyCh 发消息如果对端处理慢或者也来拿同一把锁就死锁了。还有就是持有锁做耗时的磁盘写入虽然不死锁但会卡住整个 Raft 状态机。解决方法是先拷贝需要的数据解锁再发 chan 或写盘。这些 Bug 在 3B 阶段几乎每个人都会遇到提前有个印象能省不少调试时间。三、Part C持久化Persistence3C3.1 3C 的核心持久化“承诺”不是持久化“结果”一句话只要重启可能导致你做出与重启前矛盾的行为就必须在返回 RPC 之前把状态写盘其实很简单只要将需要持久化的内容每次改动的时候进行持久化就可以了。3.2 persist/readPersist持久化内容与编码格式持久化内容Figure 2rf.termrf.votedForrf.logs编码顺序必须和解码顺序一致否则 readPersist 会失忆/乱序这里也是一个坑但是我这里为了方便怎么存的怎么取所以把坑跳过去了。func (rf *Raft) persist() { // Your code here (3C). // Example: // w : new(bytes.Buffer) // e : labgob.NewEncoder(w) // e.Encode(rf.xxx) // e.Encode(rf.yyy) // raftstate : w.Bytes() // rf.persister.Save(raftstate, nil) w : new(bytes.Buffer) e : labgob.NewEncoder(w) e.Encode(rf.currentTerm) e.Encode(rf.votedFor) e.Encode(rf.logs) e.Encode(rf.LastIncludedIndex) e.Encode(rf.LastIncludedTerm) raftstate : w.Bytes() snap : rf.persister.ReadSnapshot()//先读取快照 rf.persister.Save(raftstate, snap)//再持久化状态和快照 } // restore previously persisted state. func (rf *Raft) readPersist(data []byte) { if data nil || len(data) 1 { // bootstrap without any state? return } // Your code here (3C). // Example: r : bytes.NewBuffer(data) d : labgob.NewDecoder(r) var term int var vorfor int var logs []LogEntry var lastincludedindex int var lastincludedterm int if d.Decode(term) ! nil || d.Decode(vorfor) ! nil || d.Decode(logs) ! nil || d.Decode(lastincludedindex) ! nil || d.Decode(lastincludedterm) ! nil { DPrintf(readPersist err) } else { rf.currentTerm term rf.votedFor vorfor rf.logs logs rf.LastIncludedIndex lastincludedindex rf.LastIncludedTerm lastincludedterm } }3.3 何时调用 persist时机与原子性可以按谁改了谁负责 persist写成清单startElectionterm、votedForme之后RequestVote更新term/votedFor之后尤其是投票成功路径AppendEntries看到更大 term 退位时日志截断/追加时Start追加日志后关键点一定要在 handler 返回 reply 之前 persist否则崩溃重启后可能同任期重复投票造成脑裂等一系列问题。3.4 为什么 3B 正常、3C 就崩3B 都过了3C 断电测试出现 Log Inconsistency根因通常是readPersist 没写 / 解码顺序错 / logs 没恢复占位条目commitIndex/lastApplied/nextIndex/matchIndex不需要持久化它们会在重启后通过 Leader 的 LeaderCommit、以及日志复制流程动态恢复。3.5 性能与正确性的取舍persist 频率高会拖慢系统尤其心跳很频繁时心跳频率要“优雅”足够快维持领导权但不能淹没网络too many RPCs正确性优先该 persist 的地方不能省优化要在正确性上做节流/批量/减少无效 RPC四、测试和遇到的问题cd 6.5840/src make RUN-run 3B raft1 make RUN-run 3C raft13B 阶段主要折腾的是 Raft 里两个搬运者谁在什么时候推进提交、谁把已提交日志交给状态机。我对这两块做了比较彻底的重构。updateCommitIndexLeader 侧问题一开始有数组越界len和len-1混用、以及用「日志下标」去当matchIndex的下标这类逻辑错误。做法改成从后往前扫合法的提交点 NN并严格按 Figure 8Leader 只能用「当前任期里复制到多数派的那条日志」去推进commitIndex旧任期的条目只能被顺带提交。Figure 2 流水线自测时心里要有这条链Start写日志 → Leader 发AppendEntries→ Follower 确认并追加 → Leader 用matchIndex推进commitIndex并唤醒 applier → 后续心跳带上LeaderCommitFollower 跟进commitIndex并同样唤醒 applier → 双方经applyChan按序应用。实现中需要注意的点尽量不要在持锁时写 channel。等 commit 用sync.Cond少用忙等 / 固定Sleep。心跳够快以维持领导权但不要打到 RPC 风暴。readPersist这是 3C 里很隐蔽的一类问题没实现、或 Decode 顺序和 Encode 对不上节点等于「失忆」往往在断电测试里表现为大量 Log Inconsistency而纯 3B 有时还能蒙混过关。性能和正确性HeartBeatTimeout、RPC 频率和persist次数会互相拉扯变了就存最安全但心跳极密时无脑persist会把测试拖慢。可以在保证该存必存的前提下适当拉长心跳间隔、减少无意义刷盘具体以你当时通过测试的配置为准。哪些不用存commitIndex等易失状态不必持久化重启后靠 Leader 的 LeaderCommit 和日志一致性检查再对齐即可。其它 3B 测试里碰到的问题现象原因与处理Agreement 失败one(100)等闭环缺一环Leader 收到成功回复没更新提交或 Follower 更新了commitIndex却没唤醒 applier。RPC 过多too many RPCs心跳发得太勤例如 ticker 里固定短间隔全员 RPC。需要按间隔节流如配合选举/心跳超时。冲突回退慢性能测试超时nextIndex一格一格退。应实现 ConflictTerm / ConflictIndex让 Leader 整块对齐。死锁测试 hang持锁路径里 RPC 回调或 apply 过重。缩小锁粒度禁止持锁写 channel。3C持久化测试拉长后才会暴露何时persist、保的是什么我一开始在Start里就落了盘其它 RPC 路径也零零散散加了一些persist跑 3C 才发现还有路径没覆盖全。要点持久化保的不是业务结果而是 承诺——凡是崩溃重启后可能做出和崩溃前矛盾的事例如同一任期投两次票就要在 对外承诺已经形成之后、RPC 返回之前 把该存的状态写盘。applier应用侧问题早期用Sleep轮询commitIndex测试反馈慢还有在持锁时往applyChan里送消息容易把整个节点卡死。做法用sync.Cond在commitIndex前进时Broadcast发送 apply 消息时坚持 锁里只拷贝、锁外再写 channel避免 channel 阻塞拖死持锁路径。这是最终测试通过的输出3Blcziv-yef3xahqtc5i3z5jzmr5:~/mit6.5840/6.5840/src$ make RUN-run 3B raft1go build -race -o main/raft1d main/raft1d.go cd raft1 go test -v -race -run 3B RUN TestBasicAgree3B Test (3B): basic agreement (reliable network)... ... Passed -- time 0.4s #peers 3 #RPCs 14 #Ops 3--- PASS: TestBasicAgree3B (0.71s) RUN TestRPCBytes3B Test (3B): RPC byte count (reliable network)... ... Passed -- time 1.8s #peers 3 #RPCs 58 #Ops 11--- PASS: TestRPCBytes3B (2.14s) RUN TestFollowerFailure3B Test (3B): test progressive failure of followers (reliable network)...... Passed -- time 4.3s #peers 3 #RPCs 188 #Ops 3--- PASS: TestFollowerFailure3B (4.67s) RUN TestLeaderFailure3B Test (3B): test failure of leaders (reliable network)...... Passed -- time 4.7s #peers 3 #RPCs 294 #Ops 3--- PASS: TestLeaderFailure3B (5.03s) RUN TestFailAgree3B Test (3B): agreement after follower reconnects (reliable network)...... Passed -- time 3.9s #peers 3 #RPCs 134 #Ops 7--- PASS: TestFailAgree3B (4.37s) RUN TestFailNoAgree3B Test (3B): no agreement if too many followers disconnect (reliable network)...... Passed -- time 3.3s #peers 5 #RPCs 316 #Ops 2--- PASS: TestFailNoAgree3B (3.81s) RUN TestConcurrentStarts3B Test (3B): concurrent Start()s (reliable network)... ... Passed -- time 0.6s #peers 3 #RPCs 24 #Ops 0--- PASS: TestConcurrentStarts3B (1.07s) RUN TestRejoin3B Test (3B): rejoin of partitioned leader (reliable network)...... Passed -- time 5.7s #peers 3 #RPCs 282 #Ops 4--- PASS: TestRejoin3B (6.05s) RUN TestBackup3B Test (3B): leader backs up quickly over incorrect follower logs (reliable network)...... Passed -- time 19.1s #peers 5 #RPCs 2568 #Ops 102--- PASS: TestBackup3B (19.68s) RUN TestCount3B Test (3B): RPC counts arent too high (reliable network)...... Passed -- time 2.2s #peers 3 #RPCs 72 #Ops 0--- PASS: TestCount3B (2.71s) PASS ok 6.5840/raft1 51.273s3Clcziv-yef3xahqtc5i3z5jzmr5:~/mit6.5840/6.5840/src$ make RUN-run 3C raft1go build -race -o main/raft1d main/raft1d.gocd raft1 go test -v -race -run 3C RUN TestPersist13CTest (3C): basic persistence (reliable network)...... Passed -- time 3.3s #peers 3 #RPCs 98 #Ops 6--- PASS: TestPersist13C (3.75s) RUN TestPersist23CTest (3C): more persistence (reliable network)...... Passed -- time 13.7s #peers 5 #RPCs 568 #Ops 16--- PASS: TestPersist23C (14.36s) RUN TestPersist33CTest (3C): partitioned leader and one follower crash, leader restarts (reliable network)...... Passed -- time 1.5s #peers 3 #RPCs 48 #Ops 4--- PASS: TestPersist33C (1.84s) RUN TestFigure83CTest (3C): Figure 8 (reliable network)...2026/03/18 22:15:05 6PCdkEFTs2eiMT_RlFB1: dmxsrv.reader: clnt ACu3swj2_8gbs1Wd6nbn ReadCall err read unix /tmp/6.5840-6PCdkEFTs2eiMT_RlFB1-: read: connection reset by peer2026/03/18 22:15:47 6PCdkEFTs2eiMT_RlFB1: dmxsrv.reader: clnt 5VPxjteaE_i4P1o9h71T ReadCall err read unix /tmp/6.5840-6PCdkEFTs2eiMT_RlFB1-: read: connection reset by peer... Passed -- time 51.8s #peers 5 #RPCs 2369 #Ops 2--- PASS: TestFigure83C (52.30s) RUN TestUnreliableAgree3CTest (3C): unreliable agreement (unreliable network)...... Passed -- time 3.4s #peers 5 #RPCs 220 #Ops 246--- PASS: TestUnreliableAgree3C (4.02s) RUN TestFigure8Unreliable3CTest (3C): Figure 8 (unreliable) (unreliable network)...... Passed -- time 48.0s #peers 5 #RPCs 7496 #Ops 22026/03/18 22:16:44 T5AgHTtizWPRzjsYwAQ6: dmxsrv.reader: clnt UkD_e2Q-b5OG3f1PBPSa ReadCall err read unix /tmp/6.5840-T5AgHTtizWPRzjsYwAQ6-: read: connection reset by peer--- PASS: TestFigure8Unreliable3C (48.77s) RUN TestReliableChurn3CTest (3C): churn (reliable network)...... Passed -- time 16.6s #peers 5 #RPCs 1084 #Ops 1--- PASS: TestReliableChurn3C (17.17s) RUN TestUnreliableChurn3CTest (3C): unreliable churn (unreliable network)...... Passed -- time 16.8s #peers 5 #RPCs 1028 #Ops 1--- PASS: TestUnreliableChurn3C (17.46s)PASSok 6.5840/raft1 160.685s五、收获在看完论文理解之后lab3还是较简单的但是对于test中其实并不能test出你代码的漏洞就像我之前ticker设置的检索间隔一样。照样是通过了所有test。但是在B中却因为RPC调用太频繁超时了。我们在代码实现中要使用尽量多的调试信息打印以便后续调试希望我的思路可以带给你们思路然后按照自己的思路实现出属于自己的lab1。最后希望有错误的地方多指正指正~完整实现mit6.5840: 用来记录mit6.5840原6.824的实现历程觉得有收获的可以帮忙点个star~

相关文章:

MIT 6.824 lab3B/C

前言 花两天把lab3B/C写了一下,有了A的基础,简单了不少。gitee地址放在末尾。 一、3B/3C 前的整体认知 1.1 3B 的目标 Leader 接收 Start(command) → 追加到 rf.logs → 复制到多数派 → 推进 commitIndex → 通过 applyChan 交给状态机。 1.2 3C 的…...

ORM调用mysql库函数,实现时间+天数

时间字段天数字段计算后时间调用数据库DATE_ADD构建ORM可使用的公共方法class DateAdd(Func):function DATE_ADDdef __init__(self, expression, bufferday1, **extra):self.template %(function)s(%(expressions)s, INTERVAL {} DAY).format(bufferday)super(DateAdd, self)…...

深度学习(4)自动求导

1. 向量链式法则① 例子1是一个线性回归的例子,如下图所示。内积是一个标量,相当于对标量求导标量对行向量求导结果还是行向量这时,X是一个矩阵这里统一采用分子布局,分子布局和分母布局只差一个转置。I为单位矩阵2. 自动求导3. 计…...

【Linux3】压缩解压缩,命令解释器,账户和组管理,文件系统权限

1.压缩解压缩:压缩:下载unzip:自动压缩tar (归档)压缩后剩10M这里605行是压缩格式,613行是解压格式tar(归档)命令可以直接用gz进行压缩,直接一步压缩为10M解压:指定解压路径2.命令解…...

南京邮电大学电装实习报告-2026版

...

凸包(Convex Hull)

目录 1、前言 1.1什么是凸包 2、算法基础铺垫 2.1数学基础 2.1.1叉积 2.2数据结构基础 2.2.1栈 3、算法实现(C) 3.1算法(Andrew)讲解 3.2代码复现 1、前言 1.1什么是凸包 给定二维平面上的点集,凸包就是将…...

Youtu-VL-4B-Instruct优化技巧:如何调整参数让图片问答更准确、描述更生动

Youtu-VL-4B-Instruct优化技巧:如何调整参数让图片问答更准确、描述更生动 当你第一次使用Youtu-VL-4B-Instruct模型时,可能会遇到这样的困惑:为什么同样的图片,有时候能得到详细生动的描述,有时候回答却简短模糊&…...

fpga系列 HDL : Microchip FPGA开发软件 Libero Soc选择RAM IP(Two Port IP核)

Catalog下选择ram IP 特性RAM - Dual PortRAM - Two Port别名通常指 True Dual-Port RAM通常指 Simple Dual-Port RAM端口功能两个端口均可读可写 (R/W)端口功能分离:一个端口只写,另一个端口只读端口定义端口A和端口B是对等的,都可以独立进行…...

【vllm】(二)vLLM v1 Engine — 模块超深度逐行分析之三

3.10 core.py - 引擎核心文件职责: 实现vLLM推理的"内循环"——调度→执行→更新,这是GPU推理的真正驱动者。 3.10.1 EngineCore.init() 初始化流程 逐行解析: 加载插件: load_general_plugins() — 允许第三方插件注册创建ModelExecutor: exe…...

【Applicom】applicom PC Network Interfaces - Version 下载分享

applicom PC Network Interfaces 3.1-4.3applicom PC Network Interfaces 软件 介绍软件列表:使用注意相关资料下载地址applicom PC Network Interfaces 软件 介绍 找了很久才在一个网站找到的软件包,很多个版本,不常用软件,但是很难找全版本…...

ACM周报5

牛客周赛140:B题:s.find(m)时间复杂度是O(m)的,所以可能超时,可以用栈模拟,从后往前D,E题:本质是连通块问题,可以将所有ix和iy不超过n的位置放入一个集合中,用并查集实现&#xff0c…...

深度解析YOLOv11多光谱目标检测的技术实现与性能优化

深度解析YOLOv11多光谱目标检测的技术实现与性能优化 【免费下载链接】ultralytics Ultralytics YOLO 🚀 项目地址: https://gitcode.com/GitHub_Trending/ul/ultralytics 在农业监测、夜间安防、遥感分析等复杂视觉场景中,多光谱目标检测技术通过…...

Linux 0.11源码深度解析:kernel/chr_drv/tty_io.c —— 终端I/O的控制中枢与行规约引擎

一、文件概述:用户与内核的交互桥梁tty_io.c​ 位于 /kernel/chr_drv目录,是Linux 0.11中终端(Terminal/TTY)输入输出的核心实现。在1991年的命令行时代,终端是用户与计算机交互的唯一窗口。这个文件负责管理键盘输入的…...

Stable Yogi Leather-Dress-Collection 模型文件管理与版本控制实践

Stable Yogi Leather-Dress-Collection 模型文件管理与版本控制实践 你是不是也遇到过这种情况:好不容易下载了一堆模型文件,有主模型、VAE、LoRA,还有各种配置文件,全都堆在下载文件夹里。过两天想用某个特定版本的模型&#xf…...

树莓派4B双WIFI自动切换配置指南:告别手动切换,实现网络无缝漫游

树莓派4B双WIFI智能切换实战:打造永不掉线的网络冗余系统 在移动办公和物联网部署场景中,网络连接的稳定性直接决定了设备的工作可靠性。想象一下这些场景:正在进行的远程数据同步因办公室WiFi故障而中断,户外展示设备因场地网络变…...

不止RealVNC!横向评测Windows远程访问树莓派的3种图形化方案(含RDP、AnyDesk)

树莓派远程桌面方案深度评测:RealVNC、RDP与AnyDesk实战对比 树莓派作为一款功能强大的微型计算机,经常需要远程访问其图形界面进行操作。对于Windows用户而言,选择合适的远程桌面工具直接影响工作效率和体验。本文将深入评测三种主流方案&am…...

豆包AI模拟面试官,提示词迭代记录

引言 某招聘软件的AI面试,问题死板、数量固定、中途打断、随意打分,和真实面试完全不是一回事。所以我用豆包AI提示词,自己做了个能模拟真实面试的AI面试官。 文档目的 我突然想到这个点子之后,实际使用一次后感觉效果极好&#x…...

设计模式基础与SOLID原则

🏗️ 设计模式基础与SOLID原则 设计模式是软件开发中经过验证的、可复用的解决方案。掌握设计模式,能够让我们的代码更加优雅、可维护、可扩展。 一、什么是设计模式 设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经…...

从 LLM 到 Agent:“工具”和“主动性”?

最近AI概念实在是太火,后端java仔不得不跟上时代。 从大语言模型出现以后,人们发现它可以写论文、写代码、做总结、回答问题,表现得非常强大。但在实际使用中,也逐渐暴露出几个明显问题: 第一,幻觉严重。…...

告别报销烦恼!金蝶AI星辰费用报销实操指南,让企业效率飞起来

还在为繁琐的费用报销流程头疼吗?员工填单慢、财务审核累、老板看不清账?别担心,金蝶AI星辰带着“云报销”功能来拯救你了!今天,我们就用一篇通俗易懂的实操指南,带你体验从“报销难”到“报销爽”的华丽蜕…...

(10个核心知识点解构分章版)深度解析TCP/IP网络协议栈:从基础概念到核心机制的全方位指南

(10个核心知识点解构分章版)深度解析TCP/IP网络协议栈:从基础概念到核心机制的全方位指南作者:培风图南以星河揽胜 发布日期:2026-04-24 标签:#计算机网络 #TCP/IP #面试必备 #网络原理 #CSDN原创前言:为什么我们需要深…...

一条查询跑了 8 小时,改写后 519 毫秒?金仓子查询等价谓词传递优化深度解析

引言:明明有 WHERE 条件,为什么数据库还是全表扫描?你有没有遇到过这样的场景:写了一条 SQL,外层明明带了精确的 WHERE 过滤条件,但执行计划一看——子查询内部仍然是全表扫描,没有利用到任何过…...

为什么WHERE中的函数调用会引发灾难?揭秘KES与Oracle的函数执行顺序之谜

在 WHERE 子句里放一个"有副作用"的函数,就像在高速公路上放了一个随机变道的司机——也许今天没事,但迟早会出事故。引言:一段看起来"理所当然"的代码在一次代码评审中,我看到了这样一条 SQL:SEL…...

深度拆解 HermesAgent(二):闭环学习系统 —— AI Agent 如何“自我进化“?

深度拆解 HermesAgent(二):闭环学习系统 —— AI Agent 如何"自我进化"? 系列导读:本文是 HermesAgent 深度拆解系列 的第二篇。我们将深入分析 HermesAgent 最核心的创新——闭环学习系统,看看 …...

数据结构入门:栈实现全解析

个人专栏:《数据结构-初阶》《经典OJ题目》《C语言》 欢迎各位大佬交流! 目录 一、栈的概念及结构 1、栈的基本概念 2、栈的结构 二、代码实现 0、初始化 1、入栈 2、出栈 3、返回栈顶元素 4、获取栈中有效元素个数 5、检测栈是否为空 6、销毁…...

Sambert多情感语音合成部署教程:一键启动,快速体验AI语音生成

Sambert多情感语音合成部署教程:一键启动,快速体验AI语音生成 1. 引言:为什么选择Sambert语音合成? 在当今数字化时代,语音合成技术已经广泛应用于智能客服、有声读物、虚拟助手等领域。然而,传统语音合成…...

Keras深度学习多分类实战:从数据预处理到模型部署

1. 深度学习多分类实战:基于Keras的完整指南在计算机视觉和自然语言处理领域,多分类问题就像一位超市理货员需要将商品准确归到不同货架——MNIST手写数字识别要把图像分到0-9共10个类别,新闻主题分类则需将文章划入政治、经济或体育等板块。…...

Python Flask工程目录解读

📁 项目根目录 usedCar 项目主目录,是整个工程的工作区。📁 applications — 应用核心 Flask 应用的工厂模式组织目录,包含业务应用的初始化、扩展管理和全局配置。子目录/文件作用config.py应用全局配置文件,包含数据…...

AAEON GENE-EHL5工业级单板计算机解析与应用

1. AAEON GENE-EHL5 3.5英寸单板计算机概述AAEON GENE-EHL5是一款基于Intel Elkhart Lake处理器的3.5英寸单板计算机(SBC),专为工业自动化和边缘计算应用设计。这款紧凑型主板采用了Intel Atom x6000E系列、Pentium和Celeron处理器,在146101.7mm的标准3.…...

RWKV7-1.5B-G1A模型效果展示:对比传统LSTM在文本生成上的优势

RWKV7-1.5B-G1A模型效果展示:对比传统LSTM在文本生成上的优势 1. 开场亮点 最近测试了RWKV7-1.5B-G1A这个新模型,它在文本生成上的表现确实让人眼前一亮。特别是和传统LSTM对比时,差异更加明显。记得去年用LSTM做文本生成时,经常…...