[{"data":1,"prerenderedAt":6608},["ShallowReactive",2],{"series:index":3,"content:\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl12-cachecoherence":972,"surround:\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl12-cachecoherence":6605},[4,15,25,35,45,54,64,74,82,91,101,110,120,129,138,147,152,162,172,181,189,194,203,213,223,233,243,253,263,273,283,293,303,313,323,333,339,348,357,366,372,381,391,401,410,420,429,439,448,457,467,476,485,494,504,513,522,531,540,549,559,569,578,587,596,605,610,620,629,638,644,649,658,666,674,679,687,692,700,708,716,724,732,740,749,758,766,774,779,787,796,805,814,823,831,836,845,850,855,863,871,879,887,895,900,905,914,923,931,939,947,955,963],{"stem":5,"path":6,"title":7,"date":8,"collapsed":9,"readingTime":10},"posts\u002F2024\u002FXZZD-Aquire-Score","\u002F2024\u002F10\u002F23\u002FXZZD-Aquire-Score","XZZD_Aquire_Score","2024-10-23 15:08:30",false,{"text":11,"minutes":12,"time":13,"words":14},"3 min read",2.955,177300,591,{"stem":16,"path":17,"title":18,"date":19,"collapsed":9,"readingTime":20},"posts\u002F2024\u002Felec-design-contest-2024","\u002F2024\u002F07\u002F07\u002Felec-design-contest-2024","东四——隐秘的角落","2024-07-07 11:44:32",{"text":21,"minutes":22,"time":23,"words":24},"2 min read",1.74,104400,348,{"stem":26,"path":27,"title":28,"date":29,"collapsed":9,"readingTime":30},"posts\u002F2024\u002Fmechanics","\u002F2024\u002F07\u002F08\u002Fmechanics","about力学","2024-07-08 14:14:07",{"text":31,"minutes":32,"time":33,"words":34},"9 min read",8.54,512400,1708,{"stem":36,"path":37,"title":38,"date":39,"collapsed":9,"readingTime":40},"posts\u002F2025\u002F25GElecDesignContest","\u002F2025\u002F08\u002F26\u002F25GElecDesignContest","纪念最好的大二五组 - Soleil 的 电赛回忆录","2025-08-26 11:06:33",{"text":41,"minutes":42,"time":43,"words":44},"30 min read",29.99,1799400,5998,{"stem":46,"path":47,"title":48,"date":49,"collapsed":9,"readingTime":50},"posts\u002F2025\u002FEngineering-Innovation","\u002F2025\u002F01\u002F20\u002FEngineering-Innovation","工程实践与创新能力大赛","2025-01-20 22:20:59",{"text":21,"minutes":51,"time":52,"words":53},1.365,81900,273,{"stem":55,"path":56,"title":57,"date":58,"collapsed":9,"readingTime":59},"posts\u002F2025\u002FTOP","\u002F2025\u002F01\u002F20\u002FTOP","置顶","3025-01-20 21:53:36",{"text":60,"minutes":61,"time":62,"words":63},"1 min read",0.285,17100,57,{"stem":65,"path":66,"title":67,"date":68,"collapsed":9,"readingTime":69},"posts\u002FUGCourses\u002F1.freshman-spring\u002Fengineering-drawing-notes","\u002F2024\u002F06\u002F30\u002Fengineering-drawing-notes","工程图学期末复习","2024-06-30 21:02:09",{"text":70,"minutes":71,"time":72,"words":73},"15 min read",14.78,886800,2956,{"stem":75,"path":76,"title":77,"date":78,"collapsed":9,"readingTime":79},"posts\u002FUGCourses\u002F1.freshman-spring\u002Findex","\u002Fugcourses\u002Ffreshman-spring","大一春夏","2024-06-30 19:15:28",{"text":80,"minutes":81,"time":81,"words":81},"0 min read",0,{"stem":83,"path":84,"title":85,"date":86,"collapsed":9,"readingTime":87},"posts\u002FUGCourses\u002F2.sophomore-autumn\u002FComplex-Analysis","\u002F2025\u002F01\u002F21\u002FComplex-Analysis","复变函数与积分变换","2025-01-21 13:23:59",{"text":11,"minutes":88,"time":89,"words":90},2.855,171300,571,{"stem":92,"path":93,"title":94,"date":95,"collapsed":9,"readingTime":96},"posts\u002FUGCourses\u002F2.sophomore-autumn\u002FFundamentalsMarxism","\u002F2025\u002F06\u002F06\u002FFundamentalsMarxism","马克思主义基本原理","2025-06-06 00:22:45",{"text":97,"minutes":98,"time":99,"words":100},"6 min read",5.54,332400,1108,{"stem":102,"path":103,"title":104,"date":105,"collapsed":9,"readingTime":106},"posts\u002FUGCourses\u002F2.sophomore-autumn\u002FMathematical-Modeling","\u002F2024\u002F09\u002F22\u002FMathematical-Modeling","数学建模（课程）","2024-09-22 19:07:42",{"text":11,"minutes":107,"time":108,"words":109},2.475,148500,495,{"stem":111,"path":112,"title":113,"date":114,"collapsed":9,"readingTime":115},"posts\u002FUGCourses\u002F2.sophomore-autumn\u002FMicroelectronic-Circuits","\u002F2025\u002F01\u002F20\u002FMicroelectronic-Circuits","电基小子","2025-01-20 23:02:49",{"text":116,"minutes":117,"time":118,"words":119},"5 min read",4.225,253500,845,{"stem":121,"path":122,"title":123,"date":124,"collapsed":9,"readingTime":125},"posts\u002FUGCourses\u002F2.sophomore-autumn\u002FMumerical-Analysis","\u002F2024\u002F09\u002F19\u002FMumerical-Analysis","数值分析方法","2024-09-19 17:12:56",{"text":11,"minutes":126,"time":127,"words":128},2.1,126000,420,{"stem":130,"path":131,"title":132,"date":133,"collapsed":9,"readingTime":134},"posts\u002FUGCourses\u002F2.sophomore-autumn\u002FProbability-Theory","\u002F2025\u002F01\u002F21\u002FProbability-Theory","概率论与数理统计","2025-01-21 12:52:11",{"text":11,"minutes":135,"time":136,"words":137},2.205,132300,441,{"stem":139,"path":140,"title":141,"date":142,"collapsed":9,"readingTime":143},"posts\u002FUGCourses\u002F2.sophomore-autumn\u002Fengineering-training","\u002F2024\u002F09\u002F17\u002Fengineering-training","工程训练","2024-09-17 21:40:26",{"text":11,"minutes":144,"time":145,"words":146},2.385,143100,477,{"stem":148,"path":149,"title":150,"date":78,"collapsed":9,"readingTime":151},"posts\u002FUGCourses\u002F2.sophomore-autumn\u002Findex","\u002Fugcourses\u002Fsophomore-autumn","大二秋冬",{"text":80,"minutes":81,"time":81,"words":81},{"stem":153,"path":154,"title":155,"date":156,"collapsed":9,"readingTime":157},"posts\u002FUGCourses\u002F2.sophomore-autumn\u002Fsolid-state-physics","\u002F2024\u002F09\u002F11\u002Fsolid-state-physics","固体物理基础","2024-09-11 19:15:26",{"text":158,"minutes":159,"time":160,"words":161},"4 min read",3.21,192600,642,{"stem":163,"path":164,"title":165,"date":166,"collapsed":9,"readingTime":167},"posts\u002FUGCourses\u002F3.sophomore-spring\u002FAIFrontier","\u002Fugcourses\u002Fsophomore-spring\u002Faifrontier","人工智能前沿","2025-06-12 14:58:16",{"text":168,"minutes":169,"time":170,"words":171},"25 min read",24.02,1441200,4804,{"stem":173,"path":174,"title":175,"date":166,"collapsed":9,"readingTime":176},"posts\u002FUGCourses\u002F3.sophomore-spring\u002FDigitalSys","\u002Fugcourses\u002Fsophomore-spring\u002Fdigitalsys","数字系统设计",{"text":177,"minutes":178,"time":179,"words":180},"45 min read",44.87,2692200,8974,{"stem":182,"path":183,"title":184,"date":166,"collapsed":9,"readingTime":185},"posts\u002FUGCourses\u002F3.sophomore-spring\u002FMaoTheory","\u002F2025\u002F06\u002F12\u002FMaoTheory","毛概",{"text":70,"minutes":186,"time":187,"words":188},14.63,877800,2926,{"stem":190,"path":191,"title":192,"date":78,"collapsed":9,"readingTime":193},"posts\u002FUGCourses\u002F3.sophomore-spring\u002Findex","\u002Fugcourses\u002Fsophomore-spring","大二春夏",{"text":80,"minutes":81,"time":81,"words":81},{"stem":195,"path":196,"title":197,"date":198,"collapsed":9,"readingTime":199},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture1","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture1","Lecture 1：摩尔定律与 CMOS","2026-09-09 19:39:00",{"text":60,"minutes":200,"time":201,"words":202},0.535,32100,107,{"stem":204,"path":205,"title":206,"date":207,"collapsed":9,"readingTime":208},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture10","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture10","Lecture 10：从 MOS 电容到 MOSFET","2026-09-10 00:10:00",{"text":209,"minutes":210,"time":211,"words":212},"18 min read",17.615,1056900,3523,{"stem":214,"path":215,"title":216,"date":217,"collapsed":9,"readingTime":218},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture11","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture11","Lecture 11：亚阈值效应与 MOSFET 尺寸缩放","2026-09-10 00:20:00",{"text":219,"minutes":220,"time":221,"words":222},"23 min read",22.35,1341000,4470,{"stem":224,"path":225,"title":226,"date":227,"collapsed":9,"readingTime":228},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture12","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture12","Lecture 12：MOSFET 尺寸缩微","2026-09-10 00:30:00",{"text":229,"minutes":230,"time":231,"words":232},"35 min read",34.225,2053500,6845,{"stem":234,"path":235,"title":236,"date":237,"collapsed":9,"readingTime":238},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture13","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture13","Lecture 13：MOS 新范式","2026-09-10 00:40:00",{"text":239,"minutes":240,"time":241,"words":242},"24 min read",23.25,1395000,4650,{"stem":244,"path":245,"title":246,"date":247,"collapsed":9,"readingTime":248},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture2","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture2","Lecture 2：半导体基础","2026-09-09 19:39:31",{"text":249,"minutes":250,"time":251,"words":252},"7 min read",6.02,361200,1204,{"stem":254,"path":255,"title":256,"date":257,"collapsed":9,"readingTime":258},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture3","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture3","Lecture 3：费米能级、载流子散射与迁移率","2026-09-09 21:00:00",{"text":259,"minutes":260,"time":261,"words":262},"13 min read",12.565,753900,2513,{"stem":264,"path":265,"title":266,"date":267,"collapsed":9,"readingTime":268},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture4","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture4","Lecture 4：漂移电流、扩散电流与产生复合","2026-09-09 23:00:00",{"text":269,"minutes":270,"time":271,"words":272},"10 min read",9.22,553200,1844,{"stem":274,"path":275,"title":276,"date":277,"collapsed":9,"readingTime":278},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture5","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture5","Lecture 5：PN 结与耗尽区","2026-09-09 23:10:00",{"text":279,"minutes":280,"time":281,"words":282},"14 min read",13.515,810900,2703,{"stem":284,"path":285,"title":286,"date":287,"collapsed":9,"readingTime":288},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture6","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture6","Lecture 6：正向偏置 PN 结与理想二极管方程","2026-09-09 23:20:00",{"text":289,"minutes":290,"time":291,"words":292},"20 min read",19.095,1145700,3819,{"stem":294,"path":295,"title":296,"date":297,"collapsed":9,"readingTime":298},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture7","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture7","Lecture 7：金半接触","2026-09-09 23:40:00",{"text":299,"minutes":300,"time":301,"words":302},"16 min read",15.195,911700,3039,{"stem":304,"path":305,"title":306,"date":307,"collapsed":9,"readingTime":308},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture8","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture8","Lecture 8：PN 结在光电领域的应用","2026-09-09 23:50:00",{"text":309,"minutes":310,"time":311,"words":312},"54 min read",53.955,3237300,10791,{"stem":314,"path":315,"title":316,"date":317,"collapsed":9,"readingTime":318},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FLecture9","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Flecture9","Lecture 9：MOS 电容","2026-09-10 00:00:00",{"text":319,"minutes":320,"time":321,"words":322},"21 min read",20.355,1221300,4071,{"stem":324,"path":325,"title":326,"date":327,"collapsed":9,"readingTime":328},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FMidtermExam","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Fmidtermexam","期中复习题","2026-09-09 23:30:00",{"text":329,"minutes":330,"time":331,"words":332},"8 min read",7.595,455700,1519,{"stem":334,"path":335,"title":336,"date":337,"collapsed":9,"readingTime":338},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002FMockExam","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices\u002Fmockexam","押题密卷","2026-09-10 00:50:00",{"text":21,"minutes":51,"time":52,"words":53},{"stem":340,"path":341,"title":342,"date":198,"collapsed":343,"readingTime":344},"posts\u002FUGCourses\u002F4.junior-autumn\u002F1.microelectronic-devices\u002Findex","\u002Fugcourses\u002Fjunior-autumn\u002Fmicroelectronic-devices","微电子器件",true,{"text":158,"minutes":345,"time":346,"words":347},3.055,183300,611,{"stem":349,"path":350,"title":351,"date":352,"collapsed":9,"readingTime":353},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F1.HistoryMetaCharacters","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fhistorymetacharacters","History & Meta Characters","2026-09-10 20:25:44",{"text":269,"minutes":354,"time":355,"words":356},9.36,561600,1872,{"stem":358,"path":359,"title":360,"date":361,"collapsed":9,"readingTime":362},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F10.PastExams\u002F1.ExamAutumn2223","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fpastexams\u002Fexamautumn2223","22-23 秋冬历年卷","2026-09-10 20:26:49",{"text":319,"minutes":363,"time":364,"words":365},20.295,1217700,4059,{"stem":367,"path":368,"title":369,"date":370,"collapsed":9,"readingTime":371},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F10.PastExams\u002F2.Exam2021","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fpastexams\u002Fexam2021","20-21 历年卷","2026-09-10 20:26:50",{"text":289,"minutes":290,"time":291,"words":292},{"stem":373,"path":374,"title":375,"date":376,"collapsed":9,"readingTime":377},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F10.PastExams\u002F3.ExamRecall1","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fpastexams\u002Fexamrecall1","不知名回忆卷 1","2026-09-10 20:26:51",{"text":116,"minutes":378,"time":379,"words":380},4.215,252900,843,{"stem":382,"path":383,"title":384,"date":385,"collapsed":9,"readingTime":386},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F10.PastExams\u002F4.ExamRecall23","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fpastexams\u002Fexamrecall23","不知名回忆卷 2\u002F3","2026-09-10 20:26:52",{"text":387,"minutes":388,"time":389,"words":390},"12 min read",11.235,674100,2247,{"stem":392,"path":393,"title":394,"date":395,"collapsed":9,"readingTime":396},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F11.Detailed\u002F1.Chapter1-Introduction","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fdetailed\u002Fchapter1-introduction","Chapter 1：Introduction","2026-09-10 20:27:26",{"text":397,"minutes":398,"time":399,"words":400},"19 min read",18.435,1106100,3687,{"stem":402,"path":403,"title":404,"date":405,"collapsed":9,"readingTime":406},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F11.Detailed\u002F2.Chapter2-IntroductionToUnix","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fdetailed\u002Fchapter2-introductiontounix","Chapter 2：Introduction to Unix","2026-09-10 20:27:40",{"text":168,"minutes":407,"time":408,"words":409},24.895,1493700,4979,{"stem":411,"path":412,"title":413,"date":414,"collapsed":9,"readingTime":415},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F11.Detailed\u002F3.Chapter3-ViAndShell","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fdetailed\u002Fchapter3-viandshell","Chapter 3：Vi and Shell","2026-09-10 20:27:41",{"text":416,"minutes":417,"time":418,"words":419},"32 min read",31.035,1862100,6207,{"stem":421,"path":422,"title":423,"date":424,"collapsed":9,"readingTime":425},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F11.Detailed\u002F4.Chapter4-Network","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fdetailed\u002Fchapter4-network","Chapter 4：Network","2026-09-10 20:27:49",{"text":239,"minutes":426,"time":427,"words":428},23.975,1438500,4795,{"stem":430,"path":431,"title":432,"date":433,"collapsed":9,"readingTime":434},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F11.Detailed\u002F5.Chapter5-Administration","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fdetailed\u002Fchapter5-administration","Chapter 5：Administration","2026-09-10 20:27:51",{"text":435,"minutes":436,"time":437,"words":438},"36 min read",35.41,2124600,7082,{"stem":440,"path":441,"title":442,"date":443,"collapsed":9,"readingTime":444},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F11.Detailed\u002F6.Chapter6-Xwindow","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fdetailed\u002Fchapter6-xwindow","Chapter 6：Xwindow","2026-09-10 20:27:53",{"text":319,"minutes":445,"time":446,"words":447},20.235,1214100,4047,{"stem":449,"path":450,"title":451,"date":452,"collapsed":9,"readingTime":453},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F11.Detailed\u002F7.Chapter7-SoftwareDevelopmentTools","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fdetailed\u002Fchapter7-softwaredevelopmenttools","Chapter 7：Software Development Tools","2026-09-10 20:27:54",{"text":209,"minutes":454,"time":455,"words":456},17.85,1071000,3570,{"stem":458,"path":459,"title":460,"date":461,"collapsed":9,"readingTime":462},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F11.Detailed\u002F8.Chapter8-CProgrammingInUnix","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fdetailed\u002Fchapter8-cprogramminginunix","Chapter 8：C Programming in Unix","2026-09-10 20:27:57",{"text":463,"minutes":464,"time":465,"words":466},"17 min read",16.855,1011300,3371,{"stem":468,"path":469,"title":470,"date":471,"collapsed":9,"readingTime":472},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F2.LinuxUnix","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Flinuxunix","Linux & Unix","2026-09-10 20:25:46",{"text":41,"minutes":473,"time":474,"words":475},29.33,1759800,5866,{"stem":477,"path":478,"title":479,"date":480,"collapsed":9,"readingTime":481},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F3.Vi","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fvi","Vi","2026-09-10 20:25:47",{"text":329,"minutes":482,"time":483,"words":484},7.95,477000,1590,{"stem":486,"path":487,"title":488,"date":489,"collapsed":9,"readingTime":490},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F4.ViCopy","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fvicopy","Vi（详细版）","2026-09-10 20:25:49",{"text":279,"minutes":491,"time":492,"words":493},13.785,827100,2757,{"stem":495,"path":496,"title":497,"date":498,"collapsed":9,"readingTime":499},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F5.Shells","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fshells","Shells","2026-09-10 20:25:51",{"text":500,"minutes":501,"time":502,"words":503},"22 min read",21.21,1272600,4242,{"stem":505,"path":506,"title":507,"date":508,"collapsed":9,"readingTime":509},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F6.Network","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fnetwork","Network","2026-09-10 20:25:54",{"text":319,"minutes":510,"time":511,"words":512},20.595,1235700,4119,{"stem":514,"path":515,"title":516,"date":517,"collapsed":9,"readingTime":518},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F7.SystemAdministration","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fsystemadministration","System Administration","2026-09-10 20:26:44",{"text":329,"minutes":519,"time":520,"words":521},7.12,427200,1424,{"stem":523,"path":524,"title":525,"date":526,"collapsed":9,"readingTime":527},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F8.XWindow","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fxwindow","XWindow","2026-09-10 20:26:45",{"text":97,"minutes":528,"time":529,"words":530},5.105,306300,1021,{"stem":532,"path":533,"title":534,"date":535,"collapsed":9,"readingTime":536},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002F9.SystemDevelopmentTools","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad\u002Fsystemdevelopmenttools","System Development Tools","2026-09-10 20:26:47",{"text":387,"minutes":537,"time":538,"words":539},11.35,681000,2270,{"stem":541,"path":542,"title":543,"date":544,"collapsed":343,"readingTime":545},"posts\u002FUGCourses\u002F4.junior-autumn\u002F2.ICCAD\u002Findex","\u002Fugcourses\u002Fjunior-autumn\u002Ficcad","面向 ICCAD 的软件基础技术","2026-09-10 12:37:00",{"text":60,"minutes":546,"time":547,"words":548},0.185,11100,37,{"stem":550,"path":551,"title":552,"date":553,"collapsed":9,"readingTime":554},"posts\u002FUGCourses\u002F4.junior-autumn\u002F3.HDL\u002FFeiQilai1","\u002Fugcourses\u002Fjunior-autumn\u002Fhdl\u002Ffeiqilai1","飞起来1.0","2026-09-10 12:51:49",{"text":555,"minutes":556,"time":557,"words":558},"105 min read",104.655,6279300,20931,{"stem":560,"path":561,"title":562,"date":563,"collapsed":9,"readingTime":564},"posts\u002FUGCourses\u002F4.junior-autumn\u002F3.HDL\u002FFeiQilai2","\u002Fugcourses\u002Fjunior-autumn\u002Fhdl\u002Ffeiqilai2","飞起来2.0","2026-09-10 12:52:06",{"text":565,"minutes":566,"time":567,"words":568},"29 min read",28.755,1725300,5751,{"stem":570,"path":571,"title":572,"date":573,"collapsed":9,"readingTime":574},"posts\u002FUGCourses\u002F4.junior-autumn\u002F3.HDL\u002FFeiQilai3","\u002Fugcourses\u002Fjunior-autumn\u002Fhdl\u002Ffeiqilai3","飞起来3.0","2026-09-10 12:52:12",{"text":116,"minutes":575,"time":576,"words":577},4.49,269400,898,{"stem":579,"path":580,"title":581,"date":582,"collapsed":9,"readingTime":583},"posts\u002FUGCourses\u002F4.junior-autumn\u002F3.HDL\u002FLecture13","\u002Fugcourses\u002Fjunior-autumn\u002Fhdl\u002Flecture13","Lecture 13：浮点数标准","2026-09-10 12:51:27",{"text":11,"minutes":584,"time":585,"words":586},2.575,154500,515,{"stem":588,"path":589,"title":590,"date":591,"collapsed":9,"readingTime":592},"posts\u002FUGCourses\u002F4.junior-autumn\u002F3.HDL\u002FLecture6","\u002Fugcourses\u002Fjunior-autumn\u002Fhdl\u002Flecture6","Lecture 6：Behavioral Modeling，非阻塞赋值","2026-09-10 12:51:12",{"text":97,"minutes":593,"time":594,"words":595},5.34,320400,1068,{"stem":597,"path":598,"title":599,"date":600,"collapsed":9,"readingTime":601},"posts\u002FUGCourses\u002F4.junior-autumn\u002F3.HDL\u002FPPTCorrespondence","\u002Fugcourses\u002Fjunior-autumn\u002Fhdl\u002Fpptcorrespondence","与PPT的对应","2026-09-10 12:52:18",{"text":269,"minutes":602,"time":603,"words":604},9.275,556500,1855,{"stem":606,"path":607,"title":608,"date":544,"collapsed":343,"readingTime":609},"posts\u002FUGCourses\u002F4.junior-autumn\u002F3.HDL\u002Findex","\u002Fugcourses\u002Fjunior-autumn\u002Fhdl","硬件描述语言原理与应用",{"text":60,"minutes":61,"time":62,"words":63},{"stem":611,"path":612,"title":613,"date":614,"collapsed":9,"readingTime":615},"posts\u002FUGCourses\u002F4.junior-autumn\u002F4.analogICDesign\u002F1.BeforeMidterm","\u002Fugcourses\u002Fjunior-autumn\u002Fanalogicdesign\u002Fbeforemidterm","期中前","2026-09-10 20:28:52",{"text":616,"minutes":617,"time":618,"words":619},"11 min read",10.835,650100,2167,{"stem":621,"path":622,"title":623,"date":624,"collapsed":9,"readingTime":625},"posts\u002FUGCourses\u002F4.junior-autumn\u002F4.analogICDesign\u002F2.MidtermExam2425","\u002Fugcourses\u002Fjunior-autumn\u002Fanalogicdesign\u002Fmidtermexam2425","24-25 期中","2026-09-10 20:29:00",{"text":21,"minutes":626,"time":627,"words":628},1.22,73200,244,{"stem":630,"path":631,"title":632,"date":633,"collapsed":9,"readingTime":634},"posts\u002FUGCourses\u002F4.junior-autumn\u002F4.analogICDesign\u002F3.FinalExamReview","\u002Fugcourses\u002Fjunior-autumn\u002Fanalogicdesign\u002Ffinalexamreview","期末考试整理","2026-09-10 20:29:09",{"text":387,"minutes":635,"time":636,"words":637},11.36,681600,2272,{"stem":639,"path":640,"title":641,"date":642,"collapsed":343,"readingTime":643},"posts\u002FUGCourses\u002F4.junior-autumn\u002F4.analogICDesign\u002Findex","\u002Fugcourses\u002Fjunior-autumn\u002Fanalogicdesign","模拟集成电路设计","2026-09-10 20:00:00",{"text":80,"minutes":81,"time":81,"words":81},{"stem":645,"path":646,"title":647,"date":78,"collapsed":9,"readingTime":648},"posts\u002FUGCourses\u002F4.junior-autumn\u002Findex","\u002Fugcourses\u002Fjunior-autumn","大三秋冬",{"text":80,"minutes":81,"time":81,"words":81},{"stem":650,"path":651,"title":652,"date":653,"collapsed":9,"readingTime":654},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F1.Chapter3-Device","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter3-device","Chapter 3：器件 Device","2026-09-10 21:14:41",{"text":249,"minutes":655,"time":656,"words":657},6.055,363300,1211,{"stem":659,"path":660,"title":661,"date":653,"collapsed":9,"readingTime":662},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F10.Chapter12-Arithmetic","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter12-arithmetic","Chapter 12：算术运算电路 Arithmetic",{"text":168,"minutes":663,"time":664,"words":665},24.245,1454700,4849,{"stem":667,"path":668,"title":669,"date":653,"collapsed":9,"readingTime":670},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F11.Chapter13-Memory","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter13-memory","Chapter 13：存储器 Memory",{"text":229,"minutes":671,"time":672,"words":673},34.235,2054100,6847,{"stem":675,"path":676,"title":677,"date":653,"collapsed":9,"readingTime":678},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F12.Chapter14","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter14","Chapter 14",{"text":80,"minutes":81,"time":81,"words":81},{"stem":680,"path":681,"title":682,"date":653,"collapsed":9,"readingTime":683},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F13.PastExams\u002F1.Midterm2022","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fpastexams\u002Fmidterm2022","2022 期中试题",{"text":60,"minutes":684,"time":685,"words":686},0.075,4500,15,{"stem":688,"path":689,"title":690,"date":653,"collapsed":9,"readingTime":691},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F13.PastExams\u002F2.Midterm2023","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fpastexams\u002Fmidterm2023","2023 期中试题",{"text":80,"minutes":81,"time":81,"words":81},{"stem":693,"path":694,"title":695,"date":653,"collapsed":9,"readingTime":696},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F13.PastExams\u002F3.FinalPolished","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fpastexams\u002Ffinalpolished","期末历年卷（AI 润色版）",{"text":21,"minutes":697,"time":698,"words":699},1.575,94500,315,{"stem":701,"path":702,"title":703,"date":653,"collapsed":9,"readingTime":704},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F14.ExamRecall2026","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fexamrecall2026","数字集成电路回忆 2026",{"text":60,"minutes":705,"time":706,"words":707},0.49,29400,98,{"stem":709,"path":710,"title":711,"date":653,"collapsed":9,"readingTime":712},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F2.Chapter4-Wire","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter4-wire","Chapter 4：导线 Wire",{"text":397,"minutes":713,"time":714,"words":715},18.65,1119000,3730,{"stem":717,"path":718,"title":719,"date":653,"collapsed":9,"readingTime":720},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F3.Chapter5-Inverter","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter5-inverter","Chapter 5：CMOS 反相器 Inverter",{"text":269,"minutes":721,"time":722,"words":723},9.385,563100,1877,{"stem":725,"path":726,"title":727,"date":653,"collapsed":9,"readingTime":728},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F4.Chapter6-LogicGate","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter6-logicgate","Chapter 6：逻辑门 Logic Gate",{"text":31,"minutes":729,"time":730,"words":731},8.635,518100,1727,{"stem":733,"path":734,"title":735,"date":653,"collapsed":9,"readingTime":736},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F5.Chapter7-SequentialLogic","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter7-sequentiallogic","Chapter 7：时序逻辑 Sequential Logic",{"text":463,"minutes":737,"time":738,"words":739},16.645,998700,3329,{"stem":741,"path":742,"title":743,"date":653,"collapsed":9,"readingTime":744},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F6.Chapter8-Speed","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter8-speed","Chapter 8：延迟与速度 Speed",{"text":745,"minutes":746,"time":747,"words":748},"33 min read",32.885,1973100,6577,{"stem":750,"path":751,"title":752,"date":653,"collapsed":9,"readingTime":753},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F7.Chapter9-Power","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter9-power","Chapter 9：功耗 Power",{"text":754,"minutes":755,"time":756,"words":757},"31 min read",31.005,1860300,6201,{"stem":759,"path":760,"title":761,"date":653,"collapsed":9,"readingTime":762},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F8.Chapter10-Interconnect","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter10-interconnect","Chapter 10：互连 Interconnect",{"text":463,"minutes":763,"time":764,"words":765},16.32,979200,3264,{"stem":767,"path":768,"title":769,"date":653,"collapsed":9,"readingTime":770},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002F9.Chapter11-Timing","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign\u002Fchapter11-timing","Chapter 11：时序 Timing",{"text":289,"minutes":771,"time":772,"words":773},19.68,1180800,3936,{"stem":775,"path":776,"title":777,"date":653,"collapsed":343,"readingTime":778},"posts\u002FUGCourses\u002F5.junior-spring\u002F1.digitalICDesign\u002Findex","\u002Fugcourses\u002Fjunior-spring\u002Fdigitalicdesign","数字集成电路设计",{"text":80,"minutes":81,"time":81,"words":81},{"stem":780,"path":781,"title":782,"date":653,"collapsed":9,"readingTime":783},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F1.L1-Intro","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl1-intro","L1：计算机发展史与体系结构导论",{"text":397,"minutes":784,"time":785,"words":786},18.695,1121700,3739,{"stem":788,"path":789,"title":790,"date":653,"collapsed":9,"readingTime":791},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F10.L8-9-Memory","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl8-9-memory","L8-9：存储器层次结构",{"text":792,"minutes":793,"time":794,"words":795},"128 min read",127.1,7626000,25420,{"stem":797,"path":798,"title":799,"date":653,"collapsed":9,"readingTime":800},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F11.L10-11-Parallelism","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl10-11-parallelism","L10-11：并行性",{"text":801,"minutes":802,"time":803,"words":804},"159 min read",158.86,9531600,31772,{"stem":806,"path":807,"title":808,"date":653,"collapsed":9,"readingTime":809},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F12.L12-CacheCoherence","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl12-cachecoherence","L12：缓存一致性 Cache Coherence",{"text":810,"minutes":811,"time":812,"words":813},"76 min read",75.395,4523700,15079,{"stem":815,"path":816,"title":817,"date":653,"collapsed":9,"readingTime":818},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F13.L13-14-ComplexPipeline","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl13-14-complexpipeline","L13-14：复杂流水线（衔接 L7）",{"text":819,"minutes":820,"time":821,"words":822},"44 min read",43.985,2639100,8797,{"stem":824,"path":825,"title":826,"date":653,"collapsed":9,"readingTime":827},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F14.L15","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl15","L15：期末复习问答",{"text":269,"minutes":828,"time":829,"words":830},9.105,546300,1821,{"stem":832,"path":833,"title":834,"date":653,"collapsed":9,"readingTime":835},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F2.L2-Binary","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl2-binary","L2：二进制数制",{"text":80,"minutes":81,"time":81,"words":81},{"stem":837,"path":838,"title":839,"date":653,"collapsed":9,"readingTime":840},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F3.L3-CMemory","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl3-cmemory","L3：C 语言与内存模型",{"text":841,"minutes":842,"time":843,"words":844},"98 min read",97.32,5839200,19464,{"stem":846,"path":847,"title":848,"date":653,"collapsed":9,"readingTime":849},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F4.L4a-wbx","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl4a-wbx","L4a：wbx",{"text":80,"minutes":81,"time":81,"words":81},{"stem":851,"path":852,"title":853,"date":653,"collapsed":9,"readingTime":854},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F5.L4b-MachineCode","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl4b-machinecode","L4b：机器码 Machine Code",{"text":80,"minutes":81,"time":81,"words":81},{"stem":856,"path":857,"title":858,"date":653,"collapsed":9,"readingTime":859},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F6.L5-DSD","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl5-dsd","L5：数字系统设计 Digital System Design",{"text":269,"minutes":860,"time":861,"words":862},9.955,597300,1991,{"stem":864,"path":865,"title":866,"date":653,"collapsed":9,"readingTime":867},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F7.L6a-SingleCycle","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl6a-singlecycle","L6a：单周期处理器设计",{"text":219,"minutes":868,"time":869,"words":870},22.125,1327500,4425,{"stem":872,"path":873,"title":874,"date":653,"collapsed":9,"readingTime":875},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F8.L6b-Microcode","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl6b-microcode","L6b：微码处理器架构",{"text":387,"minutes":876,"time":877,"words":878},11.86,711600,2372,{"stem":880,"path":881,"title":882,"date":653,"collapsed":9,"readingTime":883},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F9.L7-Pipeline","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization\u002Fl7-pipeline","L7：流水线处理器",{"text":177,"minutes":884,"time":885,"words":886},44.505,2670300,8901,{"stem":888,"path":889,"title":890,"date":653,"collapsed":343,"readingTime":891},"posts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002Findex","\u002Fugcourses\u002Fjunior-spring\u002Fcomputerorganization","计算机组成与系统结构",{"text":60,"minutes":892,"time":893,"words":894},0.12,7200,24,{"stem":896,"path":897,"title":898,"date":78,"collapsed":9,"readingTime":899},"posts\u002FUGCourses\u002F5.junior-spring\u002Findex","\u002Fugcourses\u002Fjunior-spring","大三春夏",{"text":80,"minutes":81,"time":81,"words":81},{"stem":901,"path":902,"title":903,"date":78,"collapsed":9,"readingTime":904},"posts\u002FUGCourses\u002Findex","\u002Fugcourses","本科课程",{"text":80,"minutes":81,"time":81,"words":81},{"stem":906,"path":907,"title":908,"date":909,"collapsed":9,"readingTime":910},"posts\u002Fubuntu\u002F1.config","\u002Fubuntu\u002Fconfig","ubuntu 系统配置","2025-08-26 19:38:06",{"text":158,"minutes":911,"time":912,"words":913},3.815,228900,763,{"stem":915,"path":916,"title":917,"date":918,"collapsed":9,"readingTime":919},"posts\u002Fubuntu\u002F2.cadence\u002F1.mmsim","\u002Fubuntu\u002Fcadence\u002Fmmsim","在 Ubuntu 24.04 上安装 Cadence MMSIM 15.1 的兼容性问题","2026-09-09 14:06:40",{"text":158,"minutes":920,"time":921,"words":922},3.5,210000,700,{"stem":924,"path":925,"title":926,"date":918,"collapsed":9,"readingTime":927},"posts\u002Fubuntu\u002F2.cadence\u002F2.innovus","\u002Fubuntu\u002Fcadence\u002Finnovus","Innovus安装",{"text":11,"minutes":928,"time":929,"words":930},2.08,124800,416,{"stem":932,"path":933,"title":934,"date":918,"collapsed":9,"readingTime":935},"posts\u002Fubuntu\u002F2.cadence\u002Findex","\u002Fubuntu\u002Fcadence","Ubuntu24.04安装Cadence 系列软件",{"text":269,"minutes":936,"time":937,"words":938},9.98,598800,1996,{"stem":940,"path":941,"title":942,"date":918,"collapsed":9,"readingTime":943},"posts\u002Fubuntu\u002F3.synopsys","\u002Fubuntu\u002Fsynopsys","Ubuntu 24.04 安装 Synopsys",{"text":269,"minutes":944,"time":945,"words":946},9.555,573300,1911,{"stem":948,"path":949,"title":950,"date":918,"collapsed":9,"readingTime":951},"posts\u002Fubuntu\u002F4.vivado","\u002Fubuntu\u002Fvivado","Ubuntu 24.04 安装 Vivado 2020.1",{"text":60,"minutes":952,"time":953,"words":954},0.62,37200,124,{"stem":956,"path":957,"title":958,"date":918,"collapsed":9,"readingTime":959},"posts\u002Fubuntu\u002F5.migrate","\u002Fubuntu\u002Fmigrate","硬盘迁移系统",{"text":60,"minutes":960,"time":961,"words":962},0.64,38400,128,{"stem":964,"path":965,"title":966,"date":967,"collapsed":9,"readingTime":968},"posts\u002Fubuntu\u002Findex","\u002Fubuntu","Ubuntu装进移动硬盘","2025-08-25 19:38:06",{"text":269,"minutes":969,"time":970,"words":971},9.26,555600,1852,{"id":973,"title":808,"body":974,"categories":6561,"collapsed":9,"date":653,"description":6562,"draft":9,"extension":6563,"hideInArchive":343,"hideInList":343,"image":6564,"meta":6565,"navigation":343,"path":807,"permalink":6564,"published":6564,"readingTime":6567,"recommend":6564,"references":6564,"seo":6568,"sitemap":6569,"stem":806,"tags":6600,"type":6603,"updated":653,"__hash__":6604},"content\u002Fposts\u002FUGCourses\u002F5.junior-spring\u002F2.computerOrganization\u002F12.L12-CacheCoherence.md",{"type":975,"value":976,"toc":6383},"minimark",[977,984,989,995,1015,1018,1023,1033,1036,1046,1049,1055,1057,1061,1065,1068,1085,1092,1095,1101,1104,1308,1311,1317,1323,1325,1329,1332,1338,1341,1397,1403,1405,1409,1414,1417,1423,1426,1440,1446,1448,1452,1455,1461,1463,1474,1479,1481,1485,1489,1492,1500,1503,1517,1520,1528,1530,1534,1537,1543,1545,1553,1555,1563,1568,1625,1627,1631,1634,1640,1646,1651,1653,1657,1661,1664,1670,1673,1679,1682,1688,1694,1696,1700,1703,1709,1716,1722,1725,1731,1737,1739,1743,1749,1752,1758,1761,1767,1770,1776,1783,1789,1791,1795,1801,1816,1821,1823,1827,1830,1836,1839,1845,1850,1856,1859,1865,1872,1874,1878,1882,1885,1891,1894,1900,1903,1905,1909,1913,1916,1918,1923,1925,1933,1935,1939,1942,1948,1950,1958,1960,1965,1970,1972,1976,1979,1983,1986,1992,1996,1999,2005,2012,2014,2018,2021,2141,2144,2150,2152,2156,2159,2165,2168,2174,2178,2296,2299,2305,2307,2311,2314,2320,2323,2329,2340,2342,2346,2349,2355,2359,2362,2368,2371,2377,2380,2384,2387,2392,2394,2398,2401,2407,2410,2415,2419,2422,2428,2431,2437,2440,2446,2448,2456,2458,2469,2471,2475,2479,2482,2488,2491,2497,2500,2506,2509,2514,2518,2521,2527,2530,2536,2539,2545,2550,2552,2556,2559,2565,2568,2574,2577,2583,2586,2588,2592,2595,2655,2658,2660,2664,2667,2736,2738,2744,2746,2750,2821,2824,2830,2833,2835,2839,2842,2845,2851,2854,2860,2863,2865,2869,2872,2875,2877,2883,2885,2891,2896,2899,2901,2905,2908,2914,2917,2923,2926,2932,2935,2941,2943,2949,2951,2955,2959,2965,2968,2974,2976,2980,2986,2988,2994,2997,2999,3003,3009,3011,3017,3020,3022,3026,3032,3035,3037,3051,3053,3057,3060,3064,3067,3073,3076,3082,3085,3091,3094,3096,3099,3102,3108,3111,3117,3120,3122,3126,3129,3132,3138,3145,3154,3156,3160,3166,3169,3175,3178,3180,3184,3187,3190,3193,3199,3202,3205,3212,3214,3218,3224,3230,3232,3236,3239,3245,3248,3254,3257,3260,3265,3267,3273,3276,3278,3282,3285,3291,3294,3300,3303,3309,3312,3317,3320,3326,3329,3336,3338,3342,3348,3351,3357,3361,3364,3370,3373,3376,3382,3385,3391,3394,3396,3400,3403,3406,3412,3415,3421,3428,3434,3437,3440,3446,3449,3455,3458,3460,3464,3467,3473,3476,3482,3485,3491,3497,3499,3503,3508,3511,3514,3518,3521,3527,3530,3532,3535,3538,3540,3546,3549,3555,3558,3560,3564,3567,3572,3575,3581,3584,3586,3590,3595,3602,3605,3611,3613,3619,3622,3628,3631,3637,3644,3647,3653,3656,3659,3661,3665,3670,3676,3679,3685,3688,3694,3697,3700,3703,3709,3713,3716,3722,3725,3727,3731,3736,3739,3743,3746,3752,3755,3757,3761,3764,3770,3773,3779,3782,3788,3791,3793,3796,3798,3804,3807,3813,3816,3822,3825,3830,3832,3836,3841,3844,3848,3850,3856,3859,3862,3868,3871,3874,3880,3883,3885,3889,3892,3898,3901,3907,3909,3915,3917,3921,3924,3928,3931,3933,3939,3941,3947,3950,3956,3959,3965,3968,3970,3974,3976,3982,3985,3991,3994,4000,4002,4006,4008,4014,4016,4022,4025,4027,4031,4034,4038,4041,4047,4049,4055,4058,4061,4063,4067,4070,4072,4078,4081,4084,4086,4090,4093,4099,4102,4105,4107,4114,4117,4122,4124,4128,4133,4140,4146,4150,4156,4158,4164,4167,4170,4173,4176,4182,4184,4188,4194,4196,4202,4209,4212,4215,4218,4220,4226,4228,4232,4237,4240,4247,4253,4258,4261,4267,4269,4275,4278,4280,4283,4288,4294,4300,4303,4309,4316,4322,4324,4328,4331,4337,4339,4345,4348,4351,4353,4357,4360,4366,4372,4375,4377,4381,4386,4389,4395,4398,4403,4406,4412,4415,4421,4431,4433,4437,4442,4445,4448,4454,4457,4463,4466,4468,4472,4477,4480,4486,4489,4495,4498,4501,4507,4510,4516,4519,4525,4528,4547,4550,4556,4558,4562,4567,4570,4576,4582,4585,4591,4593,4599,4602,4608,4611,4617,4620,4623,4629,4636,4638,4642,4647,4649,4653,4658,4664,4666,4672,4675,4681,4684,4687,4693,4695,4699,4704,4710,4712,4718,4720,4726,4729,4735,4737,4743,4746,4748,4752,4757,4763,4765,4771,4773,4779,4781,4787,4789,4795,4798,4800,4804,4809,4812,4815,4819,4821,4827,4829,4835,4838,4844,4847,4849,4853,4855,4861,4863,4869,4872,4874,4878,4883,4885,4891,4901,4904,4910,4913,4919,4922,4928,4931,4934,4940,4943,4945,4949,4954,4957,4963,4967,4973,4976,4982,4985,4987,4991,4996,4998,5004,5007,5013,5015,5021,5024,5026,5030,5035,5038,5044,5046,5052,5055,5061,5063,5069,5072,5078,5081,5087,5094,5097,5103,5106,5108,5112,5117,5120,5123,5128,5131,5134,5137,5143,5146,5148,5151,5154,5160,5163,5169,5172,5179,5185,5188,5190,5194,5199,5202,5205,5208,5214,5217,5223,5226,5229,5235,5238,5241,5247,5250,5252,5256,5261,5264,5267,5273,5276,5279,5282,5288,5291,5294,5300,5303,5309,5312,5318,5321,5327,5329,5340,5346,5366,5368,5372,5377,5384,5387,5393,5399,5401,5407,5410,5416,5419,5422,5428,5431,5437,5440,5446,5449,5451,5455,5460,5466,5469,5475,5478,5484,5487,5493,5496,5558,5561,5567,5588,5594,5600,5603,5609,5612,5614,5618,5623,5626,5630,5633,5636,5642,5645,5651,5654,5660,5663,5669,5672,5674,5678,5681,5683,5689,5691,5697,5700,5706,5709,5715,5717,5721,5726,5986,5989,5992,5998,6001,6007,6010,6016,6018,6024,6027,6033,6036,6042,6045,6047,6053,6055,6060,6062,6068,6071,6077,6080,6086,6094,6096,6100,6105,6108,6112,6115,6121,6124,6126,6130,6133,6136,6142,6145,6151,6154,6160,6163,6169,6171,6175,6178,6184,6187,6190,6196,6198,6202,6205,6208,6214,6217,6219,6225,6228,6230,6234,6239,6245,6247,6253,6256,6262,6264,6268,6271,6274,6280,6283,6289,6292,6294,6298,6301,6303,6309,6311,6317,6320,6322,6326,6329,6335,6338,6344,6347,6353,6356,6359,6361,6364,6367,6373,6376],[978,979,980],"blockquote",{},[981,982,983],"p",{},"Rnh is my  Snoopy",[985,986,988],"h2",{"id":987},"l12-cache-coherence缓存一致性笔记","L12 Cache Coherence｜缓存一致性笔记",[978,990,991],{},[985,992,994],{"id":993},"后面带页数的可以看-都检查过","后面带页数的可以看 都检查过",[978,996,997,1005,1008],{},[981,998,999,1000,1004],{},"来源：",[1001,1002,1003],"code",{"code":1003},"L12 Cache Coherence(4).pptx","，共 90 页。",[981,1006,1007],{},"整理方式：按“直觉 → 机制 → 例子 → tradeoff \u002F 3C \u002F AMAT 连接 → 工程 intuition → 考点”重组，而不是逐字翻译 PPT。",[981,1009,1010,1011],{},"本讲主线：",[1012,1013,1014],"strong",{},"多核共享内存为什么会出错？硬件如何用 snoopy \u002F directory 维护 coherence？coherence miss 为什么是第四个 C？coherence 和 memory consistency 到底有什么区别？",[1016,1017],"hr",{},[1019,1020,1022],"h3",{"id":1021},"_0-lecture-map本讲内容地图slides-13","0. Lecture Map｜本讲内容地图（Slides 1–3）",[981,1024,1025,1026,1029,1030],{},"这节课在整个计算机系统抽象层次中处在 ",[1012,1027,1028],{},"architecture implementation \u002F hardware architecture description"," 这一层：上层程序看到的是共享变量和 load\u002Fstore，底层真实硬件里却有多个 core、多个 private cache、共享 interconnect、memory controller。问题是：",[1012,1031,1032],{},"多个 cache 里可能同时保存同一个 memory block 的副本，这些副本如何保持一致？",[981,1034,1035],{},"本讲分成五块：",[1037,1038,1043],"pre",{"className":1039,"code":1041,"language":1042},[1040],"language-text","1. Cache Coherence Issue       多核缓存一致性问题\n2. Snoopy Cache                基于广播\u002F总线监听的一致性协议\n3. Directory Cache             基于目录的可扩展一致性协议\n4. The Fourth Cache Miss       Coherence Miss：第四类 miss\n5. Memory Consistency Model    内存一致性模型：跨地址访问顺序\n","text",[1001,1044,1041],{"__ignoreMap":1045},"",[981,1047,1048],{},"一句话总览：",[1037,1050,1053],{"className":1051,"code":1052,"language":1042},[1040],"Cache coherence 解决“同一个地址的值应该是谁”的问题；\nMemory consistency 解决“不同地址的 load\u002Fstore 顺序应该如何被其他线程观察到”的问题。\n",[1001,1054,1052],{"__ignoreMap":1045},[1016,1056],{},[985,1058,1060],{"id":1059},"_1-multiprocessor-background为什么需要多核与共享内存slides-513","1. Multiprocessor Background｜为什么需要多核与共享内存（Slides 5–13）",[1019,1062,1064],{"id":1063},"_11-为什么-2005-年左右转向多核power-wall-multicore","1.1 为什么 2005 年左右转向多核？｜Power Wall → Multicore",[981,1066,1067],{},"PPT 的练习题问：从单处理器转向多处理器的主要原因是什么？",[1069,1070,1071,1079,1082],"ul",{},[1072,1073,1074,1075,1078],"li",{},"I：",[1012,1076,1077],{},"power wall"," 出现，不能再靠更高 clock rate 和更高功耗换性能。",[1072,1080,1081],{},"II：用多个相对高效的处理器替代一个越来越低效的大处理器。",[1072,1083,1084],{},"III：OpenMP 让并行编程突然变简单。",[981,1086,1087,1088,1091],{},"考试角度答案：",[1012,1089,1090],{},"ORANGE：I & II only","。",[981,1093,1094],{},"关键不是 OpenMP 本身，而是硬件 scaling 遇到功耗墙。过去靠频率提升获得性能：",[1037,1096,1099],{"className":1097,"code":1098,"language":1042},[1040],"raise clock frequency → more performance\n",[1001,1100,1098],{"__ignoreMap":1045},[981,1102,1103],{},"但频率和电压提高会让功耗与散热不可承受：",[1105,1106,1109],"span",{"className":1107},[1108],"katex-display",[1105,1110,1113,1174],{"className":1111},[1112],"katex",[1105,1114,1117],{"className":1115},[1116],"katex-mathml",[1118,1119,1122],"math",{"xmlns":1120,"display":1121},"http:\u002F\u002Fwww.w3.org\u002F1998\u002FMath\u002FMathML","block",[1123,1124,1125,1169],"semantics",{},[1126,1127,1128,1132,1135,1138,1141,1144,1148,1151,1154,1164,1166],"mrow",{},[1129,1130,1131],"mi",{},"P",[1129,1133,1134],{},"o",[1129,1136,1137],{},"w",[1129,1139,1140],{},"e",[1129,1142,1143],{},"r",[1145,1146,1147],"mo",{},"≈",[1129,1149,1150],{},"C",[1145,1152,1153],{},"×",[1155,1156,1157,1160],"msup",{},[1129,1158,1159],{},"V",[1161,1162,1163],"mn",{},"2",[1145,1165,1153],{},[1129,1167,1168],{},"f",[1170,1171,1173],"annotation",{"encoding":1172},"application\u002Fx-tex","Power \\approx C \\times V^2 \\times f",[1105,1175,1179,1218,1240,1297],{"className":1176,"ariaHidden":1178},[1177],"katex-html","true",[1105,1180,1183,1188,1194,1197,1201,1206,1211,1215],{"className":1181},[1182],"base",[1105,1184],{"className":1185,"style":1187},[1186],"strut","height:0.6833em;",[1105,1189,1131],{"className":1190,"style":1193},[1191,1192],"mord","mathnormal","margin-right:0.1389em;",[1105,1195,1134],{"className":1196},[1191,1192],[1105,1198,1137],{"className":1199,"style":1200},[1191,1192],"margin-right:0.0269em;",[1105,1202,1205],{"className":1203,"style":1204},[1191,1192],"margin-right:0.0278em;","er",[1105,1207],{"className":1208,"style":1210},[1209],"mspace","margin-right:0.2778em;",[1105,1212,1147],{"className":1213},[1214],"mrel",[1105,1216],{"className":1217,"style":1210},[1209],[1105,1219,1221,1225,1229,1233,1237],{"className":1220},[1182],[1105,1222],{"className":1223,"style":1224},[1186],"height:0.7667em;vertical-align:-0.0833em;",[1105,1226,1150],{"className":1227,"style":1228},[1191,1192],"margin-right:0.0715em;",[1105,1230],{"className":1231,"style":1232},[1209],"margin-right:0.2222em;",[1105,1234,1153],{"className":1235},[1236],"mbin",[1105,1238],{"className":1239,"style":1232},[1209],[1105,1241,1243,1247,1288,1291,1294],{"className":1242},[1182],[1105,1244],{"className":1245,"style":1246},[1186],"height:0.9474em;vertical-align:-0.0833em;",[1105,1248,1250,1253],{"className":1249},[1191],[1105,1251,1159],{"className":1252,"style":1232},[1191,1192],[1105,1254,1257],{"className":1255},[1256],"msupsub",[1105,1258,1261],{"className":1259},[1260],"vlist-t",[1105,1262,1265],{"className":1263},[1264],"vlist-r",[1105,1266,1270],{"className":1267,"style":1269},[1268],"vlist","height:0.8641em;",[1105,1271,1273,1278],{"style":1272},"top:-3.113em;margin-right:0.05em;",[1105,1274],{"className":1275,"style":1277},[1276],"pstrut","height:2.7em;",[1105,1279,1285],{"className":1280},[1281,1282,1283,1284],"sizing","reset-size6","size3","mtight",[1105,1286,1163],{"className":1287},[1191,1284],[1105,1289],{"className":1290,"style":1232},[1209],[1105,1292,1153],{"className":1293},[1236],[1105,1295],{"className":1296,"style":1232},[1209],[1105,1298,1300,1304],{"className":1299},[1182],[1105,1301],{"className":1302,"style":1303},[1186],"height:0.8889em;vertical-align:-0.1944em;",[1105,1305,1168],{"className":1306,"style":1307},[1191,1192],"margin-right:0.1076em;",[981,1309,1310],{},"于是架构设计从“一个 core 越做越快”转向：",[1037,1312,1315],{"className":1313,"code":1314,"language":1042},[1040],"many cores + parallelism + memory hierarchy + coherence protocol\n",[1001,1316,1314],{"__ignoreMap":1045},[981,1318,1319,1322],{},[1012,1320,1321],{},"工程 intuition："," 多核不是免费加速。它把单核性能问题转化为并行编程、同步、缓存一致性、内存一致性和互连扩展问题。",[1016,1324],{},[1019,1326,1328],{"id":1327},"_12-多处理器的三个核心问题share-coordinate-scale","1.2 多处理器的三个核心问题｜Share, Coordinate, Scale",[981,1330,1331],{},"PPT 给出三个问题：",[1037,1333,1336],{"className":1334,"code":1335,"language":1042},[1040],"Q1: How do they share data?       多个处理器如何共享数据？\nQ2: How do they coordinate?       多个处理器如何协调顺序？\nQ3: How many processors supported? 系统可以扩展到多少处理器？\n",[1001,1337,1335],{"__ignoreMap":1045},[981,1339,1340],{},"这三个问题正好对应本讲后续：",[1342,1343,1344,1360],"table",{},[1345,1346,1347],"thead",{},[1348,1349,1350,1354,1357],"tr",{},[1351,1352,1353],"th",{},"问题",[1351,1355,1356],{},"硬件\u002F软件机制",[1351,1358,1359],{},"本讲连接",[1361,1362,1363,1375,1386],"tbody",{},[1348,1364,1365,1369,1372],{},[1366,1367,1368],"td",{},"共享数据",[1366,1370,1371],{},"shared memory \u002F message passing",[1366,1373,1374],{},"Slides 7–12",[1348,1376,1377,1380,1383],{},[1366,1378,1379],{},"协调顺序",[1366,1381,1382],{},"locks, synchronization, fences",[1366,1384,1385],{},"Slides 78–90",[1348,1387,1388,1391,1394],{},[1366,1389,1390],{},"扩展规模",[1366,1392,1393],{},"snoopy bus vs directory network",[1366,1395,1396],{},"Slides 27–59",[981,1398,1399,1400],{},"一句话：",[1012,1401,1402],{},"共享内存让编程模型更像单机，但硬件必须付出 coherence + consistency 的代价。",[1016,1404],{},[1019,1406,1408],{"id":1407},"_13-uma-vs-numa物理内存组织","1.3 UMA vs NUMA｜物理内存组织",[1410,1411,1413],"h4",{"id":1412},"uma-smp统一内存访问","UMA \u002F SMP｜统一内存访问",[981,1415,1416],{},"UMA（Uniform Memory Access）也叫 SMP（Symmetric Multiprocessor）。所有处理器到主存的访问距离基本相同。",[1037,1418,1421],{"className":1419,"code":1420,"language":1042},[1040],"CPU0 ─ Cache ┐\nCPU1 ─ Cache ├── Shared Interconnect ── Main Memory\nCPU2 ─ Cache ┘\n",[1001,1422,1420],{"__ignoreMap":1045},[981,1424,1425],{},"特点：",[1069,1427,1428,1431,1434,1437],{},[1072,1429,1430],{},"所有内存位置访问延迟相近。",[1072,1432,1433],{},"编程模型简单，适合 shared memory。",[1072,1435,1436],{},"内存带宽是集中瓶颈。",[1072,1438,1439],{},"处理器数量增多时，所有 core 都抢同一个内存系统，扩展性差。",[981,1441,1442,1445],{},[1012,1443,1444],{},"tradeoff："," UMA 简单，但 bandwidth 不随 core 数线性增长。",[1016,1447],{},[1410,1449,1451],{"id":1450},"numa非统一内存访问","NUMA｜非统一内存访问",[981,1453,1454],{},"NUMA（Non-Uniform Memory Access）中，每个 node 有自己的本地 memory。访问本地 memory 快，访问远程 memory 慢。",[1037,1456,1459],{"className":1457,"code":1458,"language":1042},[1040],"Node0: CPU + Cache + Local Memory\nNode1: CPU + Cache + Local Memory\nNode2: CPU + Cache + Local Memory\nNodes connected by interconnect\n",[1001,1460,1458],{"__ignoreMap":1045},[981,1462,1425],{},[1069,1464,1465,1468,1471],{},[1072,1466,1467],{},"若大多数访问是本地访问，总 memory bandwidth 可随节点数增加。",[1072,1469,1470],{},"远程访问 latency 更高。",[1072,1472,1473],{},"软件\u002FOS\u002F编译器要尽量保证 data locality。",[981,1475,1476,1478],{},[1012,1477,1321],{}," NUMA 把“一个内存瓶颈”拆成“多个本地内存 + 远程访问代价”。性能好不好取决于数据放在哪里。",[1016,1480],{},[1019,1482,1484],{"id":1483},"_14-shared-memory-vs-message-passing通信模型","1.4 Shared Memory vs Message Passing｜通信模型",[1410,1486,1488],{"id":1487},"shared-memory共享地址空间","Shared Memory｜共享地址空间",[981,1490,1491],{},"共享内存中，不同处理器可以通过相同地址访问同一个变量。",[1037,1493,1498],{"className":1494,"code":1496,"language":1497,"meta":1045},[1495],"language-c","\u002F\u002F Producer\nflag = 0;\na = 10;\nflag = 1;\n\n\u002F\u002F Consumer\nwhile (!flag) {}\nx = a * y;\n","c",[1001,1499,1496],{"__ignoreMap":1045},[981,1501,1502],{},"优点：",[1069,1504,1505,1508,1511,1514],{},[1072,1506,1507],{},"编程看起来像普通 load\u002Fstore。",[1072,1509,1510],{},"支持细粒度共享。",[1072,1512,1513],{},"可用 lock \u002F critical section 做同步。",[1072,1515,1516],{},"单一 OS image 更自然。",[981,1518,1519],{},"缺点：",[1069,1521,1522,1525],{},[1072,1523,1524],{},"硬件要维护 cache coherence。",[1072,1526,1527],{},"程序员仍然要理解 synchronization 和 memory consistency。",[1016,1529],{},[1410,1531,1533],{"id":1532},"message-passing消息传递","Message Passing｜消息传递",[981,1535,1536],{},"消息传递中，每个处理器有自己的地址空间，通信通过 send \u002F receive 显式完成。",[1037,1538,1541],{"className":1539,"code":1540,"language":1497,"meta":1045},[1495],"\u002F\u002F Producer\nsend(p2, a, label);\n\n\u002F\u002F Consumer\nreceive(p1, b, label);\nx = b * y;\n",[1001,1542,1540],{"__ignoreMap":1045},[981,1544,1502],{},[1069,1546,1547,1550],{},[1072,1548,1549],{},"数据移动显式，coherence 负担小。",[1072,1551,1552],{},"更适合大规模 cluster。",[981,1554,1519],{},[1069,1556,1557,1560],{},[1072,1558,1559],{},"编程更复杂。",[1072,1561,1562],{},"细粒度共享开销很高。",[981,1564,1565],{},[1012,1566,1567],{},"对比总结",[1342,1569,1570,1589],{},[1345,1571,1572],{},[1348,1573,1574,1577,1580,1583,1586],{},[1351,1575,1576],{},"模型",[1351,1578,1579],{},"通信方式",[1351,1581,1582],{},"同步方式",[1351,1584,1585],{},"优点",[1351,1587,1588],{},"代价",[1361,1590,1591,1608],{},[1348,1592,1593,1596,1599,1602,1605],{},[1366,1594,1595],{},"Shared Memory",[1366,1597,1598],{},"共享变量",[1366,1600,1601],{},"lock \u002F fence \u002F atomic",[1366,1603,1604],{},"编程直观，细粒度共享",[1366,1606,1607],{},"coherence + consistency 成本",[1348,1609,1610,1613,1616,1619,1622],{},[1366,1611,1612],{},"Message Passing",[1366,1614,1615],{},"send \u002F receive",[1366,1617,1618],{},"消息隐式同步",[1366,1620,1621],{},"可扩展，通信显式",[1366,1623,1624],{},"编程复杂，细粒度共享贵",[1016,1626],{},[1019,1628,1630],{"id":1629},"_15-bus-management总线为什么适合-snoopy","1.5 Bus Management｜总线为什么适合 snoopy？",[981,1632,1633],{},"Bus 是共享通信线路。任意时刻通常只有一个 master 发起事务，其他 slave 可以观察地址和控制信号。",[1037,1635,1638],{"className":1636,"code":1637,"language":1042},[1040],"Master requests bus → Bus controller grants → Master drives address\u002Fdata\u002Fcontrol\nOther caches observe transaction → decide whether to respond \u002F invalidate \u002F write back\n",[1001,1639,1637],{"__ignoreMap":1045},[981,1641,1642,1643],{},"这就是 snoopy cache 的基础：",[1012,1644,1645],{},"所有 cache 都能“听见”总线上发生的读写请求。",[981,1647,1648,1650],{},[1012,1649,1444],{}," 总线天然提供广播和顺序，但带宽有限，无法扩展到很多 core。",[1016,1652],{},[985,1654,1656],{"id":1655},"_2-cache-coherence-issue缓存一致性问题slides-1426","2. Cache Coherence Issue｜缓存一致性问题（Slides 14–26）",[1019,1658,1660],{"id":1659},"_21-并行-sum-代码为什么会出问题","2.1 并行 sum 代码为什么会出问题？",[981,1662,1663],{},"PPT 给出代码：",[1037,1665,1668],{"className":1666,"code":1667,"language":1497,"meta":1045},[1495],"sum = 0;\nbegin parallel\nfor (i = 1; i \u003C= 2; i++) {\n    lock(id, myLock);\n    sum = sum + a[i];\n    unlock(id, myLock);\n}\nend parallel\nprint sum;\n",[1001,1669,1667],{"__ignoreMap":1045},[981,1671,1672],{},"假设：",[1037,1674,1677],{"className":1675,"code":1676,"language":1042},[1040],"a[1] = 3\na[2] = 7\nexpected sum = 10\n",[1001,1678,1676],{"__ignoreMap":1045},[981,1680,1681],{},"直觉上，加锁后应该正确。但 PPT 引出两个层次的问题：",[1037,1683,1686],{"className":1684,"code":1685,"language":1042},[1040],"1. lock 本身如何正确实现？\n2. 即使临界区互斥，多个 cache 中的 sum 副本是否一致？\n",[1001,1687,1685],{"__ignoreMap":1045},[981,1689,1690,1691],{},"注意：真实程序中 lock 通常会通过 atomic operation + memory ordering 保证同步；PPT 的动画主要想说明：",[1012,1692,1693],{},"如果没有 cache coherence，普通 shared variable 会在不同 cache 中产生多个不一致副本。",[1016,1695],{},[1019,1697,1699],{"id":1698},"_22-cache-coherence-problem-的本质","2.2 Cache-Coherence Problem 的本质",[981,1701,1702],{},"缓存一致性问题的根源：",[1037,1704,1707],{"className":1705,"code":1706,"language":1042},[1040],"同一个 memory address 的 block\n可能同时存在于多个 private cache 中。\n如果一个 processor 写了它，其他 processor 的旧副本怎么办？\n",[1001,1708,1706],{"__ignoreMap":1045},[981,1710,1711,1712,1715],{},"以 ",[1001,1713,1714],{"code":1714},"Sum"," 为例：",[1037,1717,1720],{"className":1718,"code":1719,"language":1042},[1040],"Initial: Memory[Sum] = 0, all caches empty\nP1 reads Sum → P1 cache has Sum = 0, valid\nP2 reads Sum → P2 cache has Sum = 0, valid\nP1 writes Sum = 3 → P1 cache has Sum = 3, dirty\nP2 writes Sum = 7 → P2 cache has Sum = 7, dirty\nP1 reads Sum → P1 may still read Sum = 3\n",[1001,1721,1719],{"__ignoreMap":1045},[981,1723,1724],{},"这时系统中可能同时存在：",[1037,1726,1729],{"className":1727,"code":1728,"language":1042},[1040],"P1 cache: Sum = 3, dirty\nP2 cache: Sum = 7, dirty\nMemory:   Sum = 0 or stale value\n",[1001,1730,1728],{"__ignoreMap":1045},[981,1732,1733,1734,1736],{},"这违反了 shared memory 的直觉：程序员以为 ",[1001,1735,1714],{"code":1714}," 是一个变量，但硬件里它变成了多个 private copies。",[1016,1738],{},[1019,1740,1742],{"id":1741},"_23-write-through-为什么也不够","2.3 Write-Through 为什么也不够？",[981,1744,1745,1746],{},"PPT 问：使用 write-through cache 是否能解决？答案：",[1012,1747,1748],{},"不能根本解决。",[981,1750,1751],{},"Write-through 只保证：",[1037,1753,1756],{"className":1754,"code":1755,"language":1042},[1040],"processor 写 cache 时，也把新值写到 memory\n",[1001,1757,1755],{"__ignoreMap":1045},[981,1759,1760],{},"但它不保证：",[1037,1762,1765],{"className":1763,"code":1764,"language":1042},[1040],"其他 cache 中已有的旧副本会自动失效或更新\n",[1001,1766,1764],{"__ignoreMap":1045},[981,1768,1769],{},"例如：",[1037,1771,1774],{"className":1772,"code":1773,"language":1042},[1040],"P1 cache has Sum = 3\nP2 writes Sum = 7 and write-through to memory\nMemory becomes 7\nP1 later reads Sum\n",[1001,1775,1773],{"__ignoreMap":1045},[981,1777,1778,1779,1782],{},"如果 P1 的 cache line 仍然 valid，P1 可能仍然读到旧的 ",[1001,1780,1781],{"code":1781},"3","。所以 write-through 只能改善 memory freshness，不能维护 cache-to-cache coherence。",[981,1784,1785,1788],{},[1012,1786,1787],{},"关键点："," coherence 的核心不是“memory 是否最新”，而是“所有 cache 对同一地址是否遵循一致的读写规则”。",[1016,1790],{},[1019,1792,1794],{"id":1793},"_24-如果没有-cache-或-sum-不可缓存呢","2.4 如果没有 cache 或 Sum 不可缓存呢？",[981,1796,1797,1798,1800],{},"如果 ",[1001,1799,1714],{"code":1714}," 不可缓存，所有访问都直接去 shared memory，那么 stale cache copy 问题消失。但这不等于并行程序一定正确：",[1069,1802,1803,1810,1813],{},[1072,1804,1805,1806,1809],{},"仍然需要 lock \u002F atomic 来保证 ",[1001,1807,1808],{"code":1808},"sum = sum + a[i]"," 的 read-modify-write 不被交错破坏。",[1072,1811,1812],{},"仍然需要 memory ordering 保证 lock\u002Funlock 对临界区内读写的顺序。",[1072,1814,1815],{},"性能会很差，因为每次访问都去主存。",[981,1817,1818,1820],{},[1012,1819,1444],{}," 不缓存共享变量可以回避 coherence，但牺牲了 memory hierarchy 的核心性能优势。",[1016,1822],{},[1019,1824,1826],{"id":1825},"_25-shared-memory-multiprocessor-的矛盾","2.5 Shared-Memory Multiprocessor 的矛盾",[981,1828,1829],{},"多处理器系统需要 cache，因为主存 bandwidth 是瓶颈：",[1037,1831,1834],{"className":1832,"code":1833,"language":1042},[1040],"每个 core 有 private cache → 减少主存访问 → 性能提高\n",[1001,1835,1833],{"__ignoreMap":1045},[981,1837,1838],{},"但 private cache 也带来 coherence problem：",[1037,1840,1843],{"className":1841,"code":1842,"language":1042},[1040],"private copies → possible stale values → shared memory abstraction broken\n",[1001,1844,1842],{"__ignoreMap":1045},[981,1846,1711,1847,1715],{},[1001,1848,1849],{"code":1849},"Memory[1000]",[1037,1851,1854],{"className":1852,"code":1853,"language":1042},[1040],"P1 reads Memory[1000] = 20 → P1 cache has 20\nP2 reads Memory[1000] = 20 → P2 cache has 20\nP0 writes Memory[1000] = 40\n",[1001,1855,1853],{"__ignoreMap":1045},[981,1857,1858],{},"问题：P1\u002FP2 cache 里的 20 是否还有效？如果有效，它们之后读到的就是旧值。硬件必须做下面两类事情之一：",[1037,1860,1863],{"className":1861,"code":1862,"language":1042},[1040],"Invalidate: 让 P1\u002FP2 的旧副本失效\nUpdate:     把新值广播给 P1\u002FP2\n",[1001,1864,1862],{"__ignoreMap":1045},[981,1866,1867,1868,1871],{},"现实中更常用的是 ",[1012,1869,1870],{},"write invalidate","，因为 bandwidth 更省。",[1016,1873],{},[985,1875,1877],{"id":1876},"_3-snoopy-cache监听式缓存一致性slides-2741","3. Snoopy Cache｜监听式缓存一致性（Slides 27–41）",[1019,1879,1881],{"id":1880},"_31-snoopy-的核心思想","3.1 Snoopy 的核心思想",[981,1883,1884],{},"Snoopy cache 的思想：",[1037,1886,1889],{"className":1887,"code":1888,"language":1042},[1040],"所有 cache 监听 shared interconnect \u002F bus 上的 memory transactions。\n一旦看到别的 processor 对自己缓存的 line 发起读\u002F写请求，\n就根据协议改变本地 line state，必要时提供数据或使副本失效。\n",[1001,1890,1888],{"__ignoreMap":1045},[981,1892,1893],{},"也就是：",[1037,1895,1898],{"className":1896,"code":1897,"language":1042},[1040],"processor 自己访问 cache\ncache 同时 snoop 别人的 bus transaction\n",[1001,1899,1897],{"__ignoreMap":1045},[981,1901,1902],{},"所以 snoopy cache 的 tag 通常需要额外 read port，或者用别的结构避免 CPU 访问与 snoop 访问冲突。",[1016,1904],{},[1019,1906,1908],{"id":1907},"_32-write-invalidate-vs-write-update写无效-vs-写更新","3.2 Write Invalidate vs Write Update｜写无效 vs 写更新",[1410,1910,1912],{"id":1911},"write-update写广播","Write Update｜写广播",[981,1914,1915],{},"每次写共享数据时，把新值广播给其他 cache。",[981,1917,1502],{},[1069,1919,1920],{},[1072,1921,1922],{},"其他处理器之后读该数据时 latency 小，因为已经更新。",[981,1924,1519],{},[1069,1926,1927,1930],{},[1072,1928,1929],{},"写频繁时产生大量 bandwidth 消耗。",[1072,1931,1932],{},"其他处理器可能根本不会再读这个值，广播浪费。",[1016,1934],{},[1410,1936,1938],{"id":1937},"write-invalidate写无效","Write Invalidate｜写无效",[981,1940,1941],{},"写之前，让其他 cache 中同一 line 的副本 invalid。",[1037,1943,1946],{"className":1944,"code":1945,"language":1042},[1040],"writer obtains exclusive ownership\nother copies become Invalid\nwriter can then write locally\n",[1001,1947,1945],{"__ignoreMap":1045},[981,1949,1502],{},[1069,1951,1952,1955],{},[1072,1953,1954],{},"节省 bandwidth。",[1072,1956,1957],{},"writer 连续多次写同一 line 时，不需要每次广播新值。",[981,1959,1519],{},[1069,1961,1962],{},[1072,1963,1964],{},"其他 processor 下次读会 miss，需要重新取数据。",[981,1966,1967,1969],{},[1012,1968,1321],{}," bandwidth 比 latency 更珍贵，所以多数 multiprocessor 使用 write invalidate。",[1016,1971],{},[1019,1973,1975],{"id":1974},"_33-snoopy-protocol-的基本动作","3.3 Snoopy Protocol 的基本动作",[981,1977,1978],{},"PPT 给出两个关键规则：",[1410,1980,1982],{"id":1981},"write-miss","Write Miss",[981,1984,1985],{},"在执行写之前，该地址在所有其他 cache 中必须 invalid。",[1037,1987,1990],{"className":1988,"code":1989,"language":1042},[1040],"Write miss \u002F write intent\n→ broadcast invalidation\n→ collect \u002F assume invalidation done depending bus protocol\n→ writer obtains line exclusively\n→ perform write\n",[1001,1991,1989],{"__ignoreMap":1045},[1410,1993,1995],{"id":1994},"read-miss","Read Miss",[981,1997,1998],{},"如果某个 cache 里有 dirty copy，则不能直接从 memory 读，因为 memory 可能 stale。",[1037,2000,2003],{"className":2001,"code":2002,"language":1042},[1040],"Read miss\n→ snoop other caches\n→ if another cache has Modified\u002Fdirty copy:\n      dirty owner supplies data or writes back\n→ requester receives latest data\n",[1001,2004,2002],{"__ignoreMap":1045},[981,2006,2007,2008,2011],{},"这里产生了 ",[1012,2009,2010],{},"intervention"," 的概念：dirty cache 必须介入，防止 memory 返回旧数据。",[1016,2013],{},[1019,2015,2017],{"id":2016},"_34-moesi-states五种常见-cache-line-状态","3.4 MOESI States｜五种常见 cache line 状态",[981,2019,2020],{},"MOESI 是一类通用 cache coherence state 的集合：",[1342,2022,2023,2045],{},[1345,2024,2025],{},[1348,2026,2027,2030,2033,2036,2039,2042],{},[1351,2028,2029],{},"State",[1351,2031,2032],{},"中文",[1351,2034,2035],{},"含义",[1351,2037,2038],{},"Memory 是否最新",[1351,2040,2041],{},"其他 cache 是否可有副本",[1351,2043,2044],{},"本 processor 写是否需要通知别人",[1361,2046,2047,2066,2085,2104,2122],{},[1348,2048,2049,2052,2055,2058,2061,2063],{},[1366,2050,2051],{},"M Modified",[1366,2053,2054],{},"已修改",[1366,2056,2057],{},"本 cache 有最新 dirty data",[1366,2059,2060],{},"否",[1366,2062,2060],{},[1366,2064,2065],{},"不需要，已经独占",[1348,2067,2068,2071,2074,2077,2079,2082],{},[1366,2069,2070],{},"O Owned",[1366,2072,2073],{},"所有者",[1366,2075,2076],{},"本 cache 有最新 data，其他 cache 可有 shared 副本",[1366,2078,2060],{},[1366,2080,2081],{},"是，其他为 S",[1366,2083,2084],{},"写仍需先获得独占",[1348,2086,2087,2090,2093,2096,2099,2101],{},[1366,2088,2089],{},"E Exclusive",[1366,2091,2092],{},"独占未改",[1366,2094,2095],{},"本 cache 独占且 clean",[1366,2097,2098],{},"是",[1366,2100,2060],{},[1366,2102,2103],{},"可静默写成 M",[1348,2105,2106,2109,2112,2115,2117,2119],{},[1366,2107,2108],{},"S Shared",[1366,2110,2111],{},"共享",[1366,2113,2114],{},"多个 cache 可有 clean copy",[1366,2116,2098],{},[1366,2118,2098],{},[1366,2120,2121],{},"写前要 invalidate others",[1348,2123,2124,2127,2130,2133,2136,2138],{},[1366,2125,2126],{},"I Invalid",[1366,2128,2129],{},"无效",[1366,2131,2132],{},"本 cache 没有有效副本",[1366,2134,2135],{},"不适用",[1366,2137,2135],{},[1366,2139,2140],{},"访问会 miss",[981,2142,2143],{},"一句话记忆：",[1037,2145,2148],{"className":2146,"code":2147,"language":1042},[1040],"M: 我改过，只有我有，memory 旧。\nE: 只有我有，但没改，memory 新。\nS: 大家可能都有，memory 新。\nO: 我负责最新数据，别人也有旧? 不，是 shared clean-looking copies，但 memory 旧。\nI: 没有。\n",[1001,2149,2147],{"__ignoreMap":1045},[1016,2151],{},[1019,2153,2155],{"id":2154},"_35-msi-protocol最基本的三状态协议","3.5 MSI Protocol｜最基本的三状态协议",[981,2157,2158],{},"MSI 只有三种状态：",[1037,2160,2163],{"className":2161,"code":2162,"language":1042},[1040],"M = Modified\nS = Shared\nI = Invalid\n",[1001,2164,2162],{"__ignoreMap":1045},[981,2166,2167],{},"每条 cache line 除了 tag\u002Fdata，还要有 state bits：",[1037,2169,2172],{"className":2170,"code":2171,"language":1042},[1040],"| state bits | address tag | data block |\n",[1001,2173,2171],{"__ignoreMap":1045},[1410,2175,2177],{"id":2176},"msi-状态转换以-p1-的某条-line-为视角","MSI 状态转换：以 P1 的某条 line 为视角",[1342,2179,2180,2196],{},[1345,2181,2182],{},[1348,2183,2184,2187,2190,2193],{},[1351,2185,2186],{},"当前状态",[1351,2188,2189],{},"事件",[1351,2191,2192],{},"下一个状态",[1351,2194,2195],{},"动作",[1361,2197,2198,2212,2225,2237,2249,2261,2273,2285],{},[1348,2199,2200,2203,2206,2209],{},[1366,2201,2202],{},"I",[1366,2204,2205],{},"P1 read miss",[1366,2207,2208],{},"S",[1366,2210,2211],{},"从 memory 或其他 cache 获取 line",[1348,2213,2214,2216,2219,2222],{},[1366,2215,2202],{},[1366,2217,2218],{},"P1 write miss",[1366,2220,2221],{},"M",[1366,2223,2224],{},"获取 line，invalidate 其他副本",[1348,2226,2227,2229,2232,2234],{},[1366,2228,2208],{},[1366,2230,2231],{},"P1 read",[1366,2233,2208],{},[1366,2235,2236],{},"hit",[1348,2238,2239,2241,2244,2246],{},[1366,2240,2208],{},[1366,2242,2243],{},"P1 write \u002F intent to write",[1366,2245,2221],{},[1366,2247,2248],{},"发送 invalidation，让其他 shared copies 失效",[1348,2250,2251,2253,2256,2258],{},[1366,2252,2208],{},[1366,2254,2255],{},"other processor intent to write",[1366,2257,2202],{},[1366,2259,2260],{},"P1 副本失效",[1348,2262,2263,2265,2268,2270],{},[1366,2264,2221],{},[1366,2266,2267],{},"P1 read\u002Fwrite",[1366,2269,2221],{},[1366,2271,2272],{},"hit，本地读写",[1348,2274,2275,2277,2280,2282],{},[1366,2276,2221],{},[1366,2278,2279],{},"other processor read",[1366,2281,2208],{},[1366,2283,2284],{},"P1 write back \u002F supply data，自己降级为 S",[1348,2286,2287,2289,2291,2293],{},[1366,2288,2221],{},[1366,2290,2255],{},[1366,2292,2202],{},[1366,2294,2295],{},"P1 write back \u002F supply data，自己失效",[981,2297,2298],{},"状态机直觉：",[1037,2300,2303],{"className":2301,"code":2302,"language":1042},[1040],"I --read miss--> S\nI --write miss--> M\nS --own write intent--> M\nS --other write intent--> I\nM --own read\u002Fwrite--> M\nM --other read--> S + writeback\u002Fsupply\nM --other write intent--> I + writeback\u002Fsupply\n",[1001,2304,2302],{"__ignoreMap":1045},[1016,2306],{},[1019,2308,2310],{"id":2309},"_36-msi-的关键-invariantm-状态的排他性","3.6 MSI 的关键 invariant｜M 状态的排他性",[981,2312,2313],{},"PPT 强调：",[1037,2315,2318],{"className":2316,"code":2317,"language":1042},[1040],"If one cache has a line in M state,\nno other cache can have a valid copy of that line.\n",[1001,2319,2317],{"__ignoreMap":1045},[981,2321,2322],{},"这条 invariant 非常重要。它保证：",[1037,2324,2327],{"className":2325,"code":2326,"language":1042},[1040],"同一个地址不会同时存在两个不同的最新值。\n",[1001,2328,2326],{"__ignoreMap":1045},[981,2330,2331,2332,2335,2336,2339],{},"如果没有这个 invariant，就会回到前面的 ",[1001,2333,2334],{"code":2334},"Sum=3"," 和 ",[1001,2337,2338],{"code":2338},"Sum=7"," 同时存在的问题。",[1016,2341],{},[1019,2343,2345],{"id":2344},"_37-mesi为什么加入-e-状态","3.7 MESI｜为什么加入 E 状态？",[981,2347,2348],{},"MESI 在 MSI 上增加 E（Exclusive but unmodified）。",[1037,2350,2353],{"className":2351,"code":2352,"language":1042},[1040],"M: Modified exclusive\nE: Exclusive but unmodified\nS: Shared\nI: Invalid\n",[1001,2354,2352],{"__ignoreMap":1045},[1410,2356,2358],{"id":2357},"e-状态的意义","E 状态的意义",[981,2360,2361],{},"如果一个 processor read miss 某个 line，并且 snoop 发现没有其他 cache 拥有副本，那么这个 line 可以进入 E，而不是 S。",[1037,2363,2366],{"className":2364,"code":2365,"language":1042},[1040],"I --read miss, not shared--> E\nE --own read--> E\nE --own write--> M   \u002F\u002F silent upgrade, no bus transaction\n",[1001,2367,2365],{"__ignoreMap":1045},[981,2369,2370],{},"相比 MSI，MESI 优化了 private data：",[1037,2372,2375],{"className":2373,"code":2374,"language":1042},[1040],"private data read into cache 后，第一次写不需要发 invalidation。\n",[1001,2376,2374],{"__ignoreMap":1045},[981,2378,2379],{},"因为既然没有其他副本，就不需要通知别人。",[1410,2381,2383],{"id":2382},"e-状态还能减少-writeback","E 状态还能减少 writeback",[981,2385,2386],{},"E 是 clean exclusive。替换时不需要写回 memory，因为 memory 本来就是最新的。",[981,2388,2389,2391],{},[1012,2390,1444],{}," MESI 需要判断 read miss 时是否 shared，因此硬件更复杂；但它显著减少 private data 的不必要 bus traffic。",[1016,2393],{},[1019,2395,2397],{"id":2396},"_38-owner-stateo-状态为什么存在","3.8 Owner State｜O 状态为什么存在？",[981,2399,2400],{},"O 状态可以看作 Shared 的一个变体：",[1037,2402,2405],{"className":2403,"code":2404,"language":1042},[1040],"Owner cache has latest data.\nOther caches may hold shared copies.\nMemory may be stale.\nOwner supplies data on read miss.\n",[1001,2406,2404],{"__ignoreMap":1045},[981,2408,2409],{},"没有 O 状态时，如果 M line 被别人读，通常要 write back 到 memory，然后双方变 S。O 状态允许 owner 不必立刻把 memory 更新到最新，而是由 owner 负责向其他请求者提供数据。",[981,2411,2412,2414],{},[1012,2413,1444],{}," 减少 memory traffic，但协议状态更复杂，需要追踪谁是 owner。",[1019,2416,2418],{"id":2417},"_310-两级-snoop-cache-优化inclusive-l2","3.10 两级 Snoop Cache 优化｜Inclusive L2",[981,2420,2421],{},"现代处理器常有",[1037,2423,2426],{"className":2424,"code":2425,"language":1042},[1040],"small L1 + larger L2\u002FL3\n",[1001,2427,2425],{"__ignoreMap":1045},[981,2429,2430],{},"如果 L2 是 inclusive：",[1037,2432,2435],{"className":2433,"code":2434,"language":1042},[1040],"L1 中的 line 必须也存在于 L2 中\n",[1001,2436,2434],{"__ignoreMap":1045},[981,2438,2439],{},"那么 snooper 可以只 snoop L2 tag：",[1037,2441,2444],{"className":2442,"code":2443,"language":1042},[1040],"L2 miss → L1 一定没有 → 不必打扰 L1\nL2 invalidation hit → 再检查\u002Finvalid L1\n",[1001,2445,2443],{"__ignoreMap":1045},[981,2447,1502],{},[1069,2449,2450,2453],{},[1072,2451,2452],{},"snoop traffic 不直接占用 CPU-L1 端口。",[1072,2454,2455],{},"降低 L1 hit path 干扰。",[981,2457,1588],{},[1069,2459,2460,2463,2466],{},[1072,2461,2462],{},"inclusive cache 会带来额外容量压力。",[1072,2464,2465],{},"L2 eviction 可能需要反向 invalid L1。",[1072,2467,2468],{},"同一地址同时被 CPU-L1 和 L2-bus 访问时仍需要 interlock。",[1016,2470],{},[985,2472,2474],{"id":2473},"_4-directory-cache目录缓存一致性slides-4259","4. Directory Cache｜目录缓存一致性（Slides 42–59）",[1019,2476,2478],{"id":2477},"_41-snoopy-为什么不可扩展","4.1 Snoopy 为什么不可扩展？",[981,2480,2481],{},"Snoopy\u002Fbroadcast 的问题：",[1037,2483,2486],{"className":2484,"code":2485,"language":1042},[1040],"任何 processor cache miss \u002F write intent\n都要广播给所有 cache。\n",[1001,2487,2485],{"__ignoreMap":1045},[981,2489,2490],{},"随着 core 数增加，瓶颈来自：",[1037,2492,2495],{"className":2493,"code":2494,"language":1042},[1040],"1. bus \u002F interconnect bandwidth 总线通信带宽\n2. snoopy tag bandwidth snoopy 标签带宽——Snooper 要不断访问 cache tag\n",[1001,2496,2494],{"__ignoreMap":1045},[981,2498,2499],{},"PPT 的 insight：",[1037,2501,2504],{"className":2502,"code":2503,"language":1042},[1040],"Most snoops do not find a match.\n",[1001,2505,2503],{"__ignoreMap":1045},[981,2507,2508],{},"也就是大多数广播其实没有必要，因为大多数其他 cache 并没有这条 line。",[981,2510,2511],{},[1012,2512,2513],{},"Snoopy 协议靠广播和所有 cache 监听来保持一致性，小规模系统很好用；但处理器数量变多后，会受到总线带宽和 tag 检查带宽限制，因为大多数广播检查其实都查不到匹配项，所以后面要引入 Directory 协议来提高可扩展性。",[1019,2515,2517],{"id":2516},"_42-directory-的核心思想","4.2 Directory 的核心思想",[981,2519,2520],{},"Directory protocol 为每个 memory line 维护 directory information：",[1037,2522,2525],{"className":2523,"code":2524,"language":1042},[1040],"line state + sharer vector \u002F owner id\n",[1001,2526,2524],{"__ignoreMap":1045},[981,2528,2529],{},"当一个 cache miss 发生时，不广播给所有 cache，而是：",[1037,2531,2534],{"className":2532,"code":2533,"language":1042},[1040],"requester → home directory\nhome directory checks who has copies\nonly contact actual sharers \u002F owner\n",[1001,2535,2533],{"__ignoreMap":1045},[981,2537,2538],{},"直觉：",[1037,2540,2543],{"className":2541,"code":2542,"language":1042},[1040],"Snoopy:  你喊一嗓子，所有人都听。\nDirectory: 你先查登记表，只找相关的人。\n",[1001,2544,2542],{"__ignoreMap":1045},[981,2546,2547,2549],{},[1012,2548,1444],{}," directory 减少无效广播，适合大规模系统；但需要额外 directory storage、更多消息步骤、复杂 transient states。",[1016,2551],{},[1019,2553,2555],{"id":2554},"_43-directory-protocol-的系统结构","4.3 Directory Protocol 的系统结构",[981,2557,2558],{},"典型结构：",[1037,2560,2563],{"className":2561,"code":2562,"language":1042},[1040],"CPU + Cache nodes\nDirectory Controller + DRAM Bank nodes\nInterconnection Network\n",[1001,2564,2562],{"__ignoreMap":1045},[981,2566,2567],{},"每个 cache line 有：",[1037,2569,2572],{"className":2570,"code":2571,"language":1042},[1040],"Cache side: tag + data + cache state\nMemory side: data + directory state + sharer vector\n",[1001,2573,2571],{"__ignoreMap":1045},[981,2575,2576],{},"假设网络：",[1037,2578,2581],{"className":2579,"code":2580,"language":1042},[1040],"reliable network\nFIFO messages between a given source-destination pair\n",[1001,2582,2580],{"__ignoreMap":1045},[981,2584,2585],{},"但即使网络可靠，delay 仍然存在，因此协议必须处理并发事务、乱序到达、pending 状态。",[1016,2587],{},[1019,2589,2591],{"id":2590},"_44-cache-states-in-directory-protocol缓存侧状态","4.4 Cache States in Directory Protocol｜缓存侧状态",[981,2593,2594],{},"PPT 给出每条 cache line 四种状态：",[1342,2596,2597,2609],{},[1345,2598,2599],{},[1348,2600,2601,2604,2607],{},[1351,2602,2603],{},"Cache State",[1351,2605,2606],{},"等价理解",[1351,2608,2035],{},[1361,2610,2611,2622,2633,2644],{},[1348,2612,2613,2616,2619],{},[1366,2614,2615],{},"C-invalid",[1366,2617,2618],{},"Nothing",[1366,2620,2621],{},"本 cache 没有该数据",[1348,2623,2624,2627,2630],{},[1366,2625,2626],{},"C-shared",[1366,2628,2629],{},"Sh",[1366,2631,2632],{},"数据在本 cache，其他节点也可能有；memory 有效",[1348,2634,2635,2638,2641],{},[1366,2636,2637],{},"C-modified",[1366,2639,2640],{},"Ex",[1366,2642,2643],{},"本 cache 独占且 modified；memory 没有最新数据",[1348,2645,2646,2649,2652],{},[1366,2647,2648],{},"C-transient",[1366,2650,2651],{},"Pending",[1366,2653,2654],{},"请求已发出，回复未收到，处于协议中间态",[981,2656,2657],{},"注意：directory 协议中 transient state 很重要，因为 network delay 让“请求发出”和“状态完成”之间存在时间窗口。",[1016,2659],{},[1019,2661,2663],{"id":2662},"_45-home-directory-states目录侧状态","4.5 Home Directory States｜目录侧状态",[981,2665,2666],{},"PPT 给出 memory line 的 directory states：",[1342,2668,2669,2680],{},[1345,2670,2671],{},[1348,2672,2673,2676,2678],{},[1351,2674,2675],{},"Directory State",[1351,2677,2035],{},[1351,2679,2038],{},[1361,2681,2682,2700,2714,2725],{},[1348,2683,2684,2687,2698],{},[1366,2685,2686],{},"R(dir)",[1366,2688,2689,2690,2693,2694,2697],{},"line 被 ",[1001,2691,2692],{"code":2692},"dir"," 中的节点 shared；若 ",[1001,2695,2696],{"code":2696},"dir=ε","，表示无人缓存",[1366,2699,2098],{},[1348,2701,2702,2705,2712],{},[1366,2703,2704],{},"W(id)",[1366,2706,2707,2708,2711],{},"line 被节点 ",[1001,2709,2710],{"code":2710},"id"," 独占修改",[1366,2713,2060],{},[1348,2715,2716,2719,2722],{},[1366,2717,2718],{},"TR(dir)",[1366,2720,2721],{},"transient read\u002Fshared 状态，等待 invalidation ACK",[1366,2723,2724],{},"取决于事务",[1348,2726,2727,2730,2733],{},[1366,2728,2729],{},"TW(id)",[1366,2731,2732],{},"transient writeback\u002Fownership transfer 状态，等待 modified owner 更新 memory\u002Fhome",[1366,2734,2735],{},"否或 pending",[981,2737,1399],{},[1037,2739,2742],{"className":2740,"code":2741,"language":1042},[1040],"Directory 是每条 memory line 的 summary state。\n它不保存所有 cache 的完整状态，但保存足够信息来找 sharers \u002F owner。\n",[1001,2743,2741],{"__ignoreMap":1045},[1016,2745],{},[1019,2747,2749],{"id":2748},"_46-snoopy-vs-directory序列化点不同","4.6 Snoopy vs Directory｜序列化点不同",[1342,2751,2752,2765],{},[1345,2753,2754],{},[1348,2755,2756,2759,2762],{},[1351,2757,2758],{},"维度",[1351,2760,2761],{},"Snoopy Coherence",[1351,2763,2764],{},"Directory Coherence",[1361,2766,2767,2778,2788,2799,2810],{},[1348,2768,2769,2772,2775],{},[1366,2770,2771],{},"全局状态",[1366,2773,2774],{},"分散在所有 cache state 中，没有集中摘要",[1366,2776,2777],{},"directory 保存 summary state",[1348,2779,2780,2782,2785],{},[1366,2781,1579],{},[1366,2783,2784],{},"广播 \u002F snoop 所有事务",[1366,2786,2787],{},"点对点，只联系 sharers \u002F owner",[1348,2789,2790,2793,2796],{},[1366,2791,2792],{},"序列化点",[1366,2794,2795],{},"bus \u002F ring 提供总顺序",[1366,2797,2798],{},"directory controller 提供 per-line ordering",[1348,2800,2801,2804,2807],{},[1366,2802,2803],{},"扩展性",[1366,2805,2806],{},"适合小规模 bus-based SMP",[1366,2808,2809],{},"适合大规模 scalable network",[1348,2811,2812,2815,2818],{},[1366,2813,2814],{},"主要瓶颈",[1366,2816,2817],{},"bus bandwidth + snoop tag bandwidth",[1366,2819,2820],{},"directory storage + message latency + protocol complexity",[981,2822,2823],{},"关键区别：",[1037,2825,2828],{"className":2826,"code":2827,"language":1042},[1040],"Snoopy: bus order serializes transactions.\nDirectory: home directory serializes transactions for a line.\n",[1001,2829,2827],{"__ignoreMap":1045},[981,2831,2832],{},"注意：directory 对每条 line 能排序，但不自动保证整个系统对所有地址都是 sequential consistency。",[1016,2834],{},[1019,2836,2838],{"id":2837},"_47-read-miss-flow读-miss-流程","4.7 Read Miss Flow｜读 miss 流程",[981,2840,2841],{},"PPT 的 read miss 场景：directory state 是 R，已有 0 个或多个 sharers。",[981,2843,2844],{},"流程：",[1037,2846,2849],{"className":2847,"code":2848,"language":1042},[1040],"1. CPU load request reaches cache.\n2. Cache load miss.\n3. Cache sends ShReq to directory.\n4. Directory receives ShReq.\n5. Directory checks line state: R(dir).\n6. Directory sets requester bit in sharer vector.\n7. Directory sends ShRep with cache line data.\n8. ShRep arrives at cache.\n9. Cache updates tag\u002Fdata\u002Fstate and returns data to CPU.\n",[1001,2850,2848],{"__ignoreMap":1045},[981,2852,2853],{},"状态变化：",[1037,2855,2858],{"className":2856,"code":2857,"language":1042},[1040],"Directory: R(dir) → R(dir ∪ {requester})\nRequester cache: I\u002FPending → S\n",[1001,2859,2857],{"__ignoreMap":1045},[981,2861,2862],{},"如果 memory 是最新的，directory 直接从 DRAM bank 返回 data。",[1016,2864],{},[1019,2866,2868],{"id":2867},"_48-write-miss-to-shared-line对-shared-line-写-miss","4.8 Write Miss to Shared Line｜对 shared line 写 miss",[981,2870,2871],{},"场景：store miss，directory state 为 R(dir)，已有多个 sharers。",[981,2873,2874],{},"目标：写者必须拿到 exclusive ownership。",[981,2876,2844],{},[1037,2878,2881],{"className":2879,"code":2880,"language":1042},[1040],"1. CPU store reaches cache.\n2. Cache store miss.\n3. Cache sends ExReq to directory.\n4. Directory receives ExReq.\n5. Directory sees state R(dir), with sharers.\n6. Directory sends InvReq to every sharer.\n7. Each sharer receives InvReq.\n8. Sharer invalidates local line and sends InvRep.\n9. Directory receives InvRep and clears sharer bits.\n10. When all sharers invalidated, directory sends ExRep to requester.\n11. ExRep reaches requester cache.\n12. Requester installs line and performs store.\n",[1001,2882,2880],{"__ignoreMap":1045},[981,2884,2853],{},[1037,2886,2889],{"className":2887,"code":2888,"language":1042},[1040],"Old sharers: S → I\nRequester:   I\u002FPending → M\nDirectory:   R(dir) → TR(dir) → W(requester)\n",[1001,2890,2888],{"__ignoreMap":1045},[981,2892,2893],{},[1012,2894,2895],{},"为什么要等所有 ACK？",[981,2897,2898],{},"因为如果某个旧 sharer 还没 invalid，它可能继续读旧值。写者在所有旧副本失效前不能真正认为自己独占。",[1016,2900],{},[1019,2902,2904],{"id":2903},"_49-directory-structure目录结构和共享向量","4.9 Directory Structure｜目录结构和共享向量",[981,2906,2907],{},"Directory information 对每个 memory line 保存：",[1037,2909,2912],{"className":2910,"code":2911,"language":1042},[1040],"line state bits\nsharing vector: one bit per processor\n",[1001,2913,2911],{"__ignoreMap":1045},[981,2915,2916],{},"例如 3 个 processor：",[1037,2918,2921],{"className":2919,"code":2920,"language":1042},[1040],"Dir state: 01 = shared\nSharer vector: [1, 0, 1]\n",[1001,2922,2920],{"__ignoreMap":1045},[981,2924,2925],{},"表示：",[1037,2927,2930],{"className":2928,"code":2929,"language":1042},[1040],"P0 and P2 have shared copies.\nMemory value is valid.\nP1 does not have this line.\n",[1001,2931,2929],{"__ignoreMap":1045},[981,2933,2934],{},"如果 state 是 modified：",[1037,2936,2939],{"className":2937,"code":2938,"language":1042},[1040],"Dir state: 10 = modified\nSharer vector can encode owner id, e.g. [0,1,0]\n",[1001,2940,2938],{"__ignoreMap":1045},[981,2942,2925],{},[1037,2944,2947],{"className":2945,"code":2946,"language":1042},[1040],"P1 has the only modified copy.\nMemory is stale.\n",[1001,2948,2946],{"__ignoreMap":1045},[1016,2950],{},[1019,2952,2954],{"id":2953},"_410-四个-directory-操作例子","4.10 四个 Directory 操作例子",[1410,2956,2958],{"id":2957},"case-aload-with-no-sharers","Case A：load with no sharers",[1037,2960,2963],{"className":2961,"code":2962,"language":1042},[1040],"Directory: not cached, sharer vector empty\nP0 load miss → ShReq\nDirectory returns value from memory\nP0 enters Shared\nDirectory marks P0 as sharer\n",[1001,2964,2962],{"__ignoreMap":1045},[981,2966,2967],{},"结果：",[1037,2969,2972],{"className":2970,"code":2971,"language":1042},[1040],"Memory valid\nP0: S\nDirectory: R({P0})\n",[1001,2973,2971],{"__ignoreMap":1045},[1016,2975],{},[1410,2977,2979],{"id":2978},"case-bload-with-sharers","Case B：load with sharers",[1037,2981,2984],{"className":2982,"code":2983,"language":1042},[1040],"Directory: R({P0})\nP1 load miss → ShReq\nDirectory returns memory value\nDirectory adds P1 to sharer vector\n",[1001,2985,2983],{"__ignoreMap":1045},[981,2987,2967],{},[1037,2989,2992],{"className":2990,"code":2991,"language":1042},[1040],"P0: S\nP1: S\nDirectory: R({P0, P1})\n",[1001,2993,2991],{"__ignoreMap":1045},[981,2995,2996],{},"多个 processor 可以同时读同一 line。",[1016,2998],{},[1410,3000,3002],{"id":3001},"case-cstore-with-sharers","Case C：store with sharers",[1037,3004,3007],{"className":3005,"code":3006,"language":1042},[1040],"Directory: R({P0, P1})\nP2 store miss → ExReq\nDirectory sends InvReq to P0 and P1\nP0\u002FP1 invalidate and ACK\nDirectory sends ExRep to P2\nP2 writes and becomes M\n",[1001,3008,3006],{"__ignoreMap":1045},[981,3010,2967],{},[1037,3012,3015],{"className":3013,"code":3014,"language":1042},[1040],"P0: I\nP1: I\nP2: M\nDirectory: W(P2)\nMemory stale\n",[1001,3016,3014],{"__ignoreMap":1045},[981,3018,3019],{},"这就是 directory 版 write invalidate。",[1016,3021],{},[1410,3023,3025],{"id":3024},"case-dload-with-owner","Case D：load with owner",[1037,3027,3030],{"className":3028,"code":3029,"language":1042},[1040],"Directory: W(P0)\nP1 load miss → ShReq\nDirectory forwards request to owner P0\nP0 supplies latest data \u002F ACK\nP0 downgrades from M to S or O depending protocol\nP1 becomes S\nDirectory updates sharer\u002Fowner state\n",[1001,3031,3029],{"__ignoreMap":1045},[981,3033,3034],{},"核心原因：memory stale，所以不能直接从 memory 返回数据。",[1016,3036],{},[981,3038,3039,3040,3043,3044,3047,3048,1091],{},"下面这几页从 ",[1012,3041,3042],{},"Directory 协议的工程细节","，转到 ",[1012,3045,3046],{},"一致性对性能的影响","，最后引出 ",[1012,3049,3050],{},"第 4 类 cache miss：coherence miss",[1016,3052],{},[985,3054,3056],{"id":3055},"第-57-页目录操作注意事项","第 57 页：目录操作注意事项",[981,3058,3059],{},"这一页讲的是：Directory 协议不是“查个表就结束”，还需要处理很多确认消息和异常情况。",[1019,3061,3063],{"id":3062},"写共享行时必须等所有-invalid-ack","写共享行时，必须等所有 invalid ACK",[981,3065,3066],{},"如果某条 cache line 现在被多个处理器共享：",[1037,3068,3071],{"className":3069,"code":3070,"language":1042},[1040],"P0: A, Shared\nP1: A, Shared\nP2: A, Shared\n",[1001,3072,3070],{"__ignoreMap":1045},[981,3074,3075],{},"现在 P3 要写 A。Directory 不能直接允许 P3 写，而是要先通知 P0、P1、P2：",[1037,3077,3080],{"className":3078,"code":3079,"language":1042},[1040],"你们的 A 副本都失效\n",[1001,3081,3079],{"__ignoreMap":1045},[981,3083,3084],{},"然后必须收到它们的确认：",[1037,3086,3089],{"className":3087,"code":3088,"language":1042},[1040],"P0 -> Directory: ACK\nP1 -> Directory: ACK\nP2 -> Directory: ACK\n",[1001,3090,3088],{"__ignoreMap":1045},[981,3092,3093],{},"只有全部 ACK 收齐，P3 才能获得独占写权限。课件也明确说，对多个 sharers 的写操作，需要在实际写之前收集并计数所有 invalidation ACK。",[1016,3095],{},[1019,3097,3098],{"id":3098},"复杂状态变化也要确认",[981,3100,3101],{},"不只是 invalidate 需要确认。只要涉及状态变化，比如：",[1037,3103,3106],{"className":3104,"code":3105,"language":1042},[1040],"Shared -> Modified\nModified owner 转移\nDirectory 等待某个 cache 回写数据\n",[1001,3107,3105],{"__ignoreMap":1045},[981,3109,3110],{},"Directory 都需要确认消息来判断：",[1037,3112,3115],{"className":3113,"code":3114,"language":1042},[1040],"这个 load\u002Fstore 到底完成了吗？\n状态能不能更新？\n",[1001,3116,3114],{"__ignoreMap":1045},[981,3118,3119],{},"否则 Directory 可能误以为某个处理器已经失效或已经拥有数据，导致一致性错误。",[1016,3121],{},[1019,3123,3125],{"id":3124},"需要临时状态-transient-states","需要临时状态 transient states",[981,3127,3128],{},"Directory 协议中有大量“请求已经发出，但回复还没回来”的中间阶段。",[981,3130,3131],{},"比如：",[1037,3133,3136],{"className":3134,"code":3135,"language":1042},[1040],"P3 请求写 A\nDirectory 已经发出 invalidate\n但 P0\u002FP1\u002FP2 还没全部 ACK\n",[1001,3137,3135],{"__ignoreMap":1045},[981,3139,3140,3141,3144],{},"这时不能简单说 A 是 Shared，也不能说 A 已经 Modified by P3。它处于一个 ",[1012,3142,3143],{},"pending \u002F transient"," 状态。",[981,3146,3147,3148,3150,3151,3153],{},"所以前面讲的 ",[1001,3149,2718],{"code":2718},"、",[1001,3152,2729],{"code":2729}," 就是为这种情况服务的。",[1016,3155],{},[1019,3157,3159],{"id":3158},"缓冲区满时需要-nack","缓冲区满时需要 NACK",[981,3161,3162,3165],{},[1001,3163,3164],{"code":3164},"NACK"," = Negative Acknowledge，否定确认。",[981,3167,3168],{},"意思是：",[1037,3170,3173],{"className":3171,"code":3172,"language":1042},[1040],"我现在处理不了你的请求，请你稍后重试。\n",[1001,3174,3172],{"__ignoreMap":1045},[981,3176,3177],{},"例如 Directory 或 cache 的请求队列满了，不能继续收消息，就可能发 NACK。课件提到，和总线类似，当缓冲区溢出时需要引入 NACK。",[1016,3179],{},[1019,3181,3183],{"id":3182},"directory-适合少数处理器共享同一数据","Directory 适合“少数处理器共享同一数据”",[981,3185,3186],{},"Directory 的优势是避免广播。",[981,3188,3189],{},"如果一条数据只被少数处理器共享，Directory 只通知相关处理器，效率高。",[981,3191,3192],{},"但如果一条数据几乎被所有处理器共享：",[1037,3194,3197],{"className":3195,"code":3196,"language":1042},[1040],"P0, P1, P2, ... P127 都有副本\n",[1001,3198,3196],{"__ignoreMap":1045},[981,3200,3201],{},"那 Directory 还是要给很多人发 invalidate，反而不一定比广播好。",[981,3203,3204],{},"所以这一页最后的意思是：",[978,3206,3207],{},[981,3208,3209],{},[1012,3210,3211],{},"Directory 适合共享者较少的情况；如果所有人都在共享同一数据，广播可能更简单。",[1016,3213],{},[985,3215,3217],{"id":3216},"第-58-页实现困难举例","第 58 页：实现困难举例",[981,3219,3220,3221,1091],{},"这一页讲两个很具体的坑：",[1012,3222,3223],{},"操作必须按顺序处理",[981,3225,3226],{},[3227,3228],"img",{"alt":3227,"src":3229},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-01.png",[1016,3231],{},[1019,3233,3235],{"id":3234},"例子-1p0-本地必须按顺序处理事务","例子 1：P0 本地必须按顺序处理事务",[981,3237,3238],{},"课件流程大概是：",[1037,3240,3243],{"className":3241,"code":3242,"language":1042},[1040],"1. P0 发送 read request for line A\n2. P1 发送 read exclusive request for line A，在 directory 等待\n3. Directory 回复 P0 的 read，并设置 sharing vector，但消息延迟\n4a\u002F4b. Directory 同时回复 P0 和 P1：\n       通知 P0 失效，给 P1 新 owner 权限\n5. P0 invalidates line A and sends ACK\n",[1001,3244,3242],{"__ignoreMap":1045},[981,3246,3247],{},"问题在于：",[1037,3249,3252],{"className":3250,"code":3251,"language":1042},[1040],"第 3 步的旧 read reply 可能很晚才到达 P0\n",[1001,3253,3251],{"__ignoreMap":1045},[981,3255,3256],{},"如果 P0 已经根据第 4 步把 A 失效了，结果第 3 步的旧数据又到达 P0，被放进 cache，那么 P0 又重新拥有了一个过期副本。",[981,3258,3259],{},"这就错了。",[981,3261,3262],{},[1012,3263,3264],{},"解决方案：P0 必须本地顺序处理事务。",[981,3266,1893],{},[1037,3268,3271],{"className":3269,"code":3270,"language":1042},[1040],"如果 P0 对 A 有一个 read 请求还挂起，\n它不能随便处理后面和 A 相关的 invalidate \u002F owner 转移。\n",[1001,3272,3270],{"__ignoreMap":1045},[981,3274,3275],{},"课件原文也指出，当第 3 步最终到达 P0 时，line A 的过期值可能被放入缓存；解决方法是 P0 必须本地顺序处理事务。",[1016,3277],{},[1019,3279,3281],{"id":3280},"例子-2directory-自己也必须按顺序处理事务","例子 2：Directory 自己也必须按顺序处理事务",[981,3283,3284],{},"第二个例子大概是：",[1037,3286,3289],{"className":3287,"code":3288,"language":1042},[1040],"1. P1 发送 read exclusive request for line A\n2. Directory 转发请求给 P0，因为 P0 是 owner\n3a. P0 把数据发给 P1\n3b. P0 给 Directory 发 ACK，但 ACK 延迟\n4. P1 收到数据后认为 read exclusive 完成；\n   后来 P1 替换这条 line，把更新值写回内存\n",[1001,3290,3288],{"__ignoreMap":1045},[981,3292,3293],{},"问题是：",[1037,3295,3298],{"className":3296,"code":3297,"language":1042},[1040],"第 4 步写回内存可能先到 Directory\n第 3b 步 ACK 反而后到\n",[1001,3299,3297],{"__ignoreMap":1045},[981,3301,3302],{},"Directory 如果没处理好，就可能：",[1037,3304,3307],{"className":3305,"code":3306,"language":1042},[1040],"先接受 P1 写回并覆盖内存\n后收到 3b，又认为所有权转移刚刚完成，P1 还是 owner\n",[1001,3308,3306],{"__ignoreMap":1045},[981,3310,3311],{},"状态就乱了。",[981,3313,3314],{},[1012,3315,3316],{},"解决方案：Directory 必须顺序处理事务。",[981,3318,3319],{},"特别是：",[1037,3321,3324],{"className":3322,"code":3323,"language":1042},[1040],"当 ownership transfer 还没完成时，\nDirectory 不能随便响应后来的 replacement\u002Fwriteback。\n",[1001,3325,3323],{"__ignoreMap":1045},[981,3327,3328],{},"这页核心就是：",[978,3330,3331],{},[981,3332,3333],{},[1012,3334,3335],{},"Directory 协议的难点不在“状态名字”，而在消息延迟和乱序到达时，如何保证同一条 cache line 的事务顺序不乱。",[1016,3337],{},[985,3339,3341],{"id":3340},"第-59-页目录的开销","第 59 页：目录的开销",[981,3343,3344,3345],{},"这一页讲 Directory 的缺点：",[1012,3346,3347],{},"目录信息本身也要占空间。",[981,3349,3350],{},"假设系统有：",[1037,3352,3355],{"className":3353,"code":3354,"language":1042},[1040],"128 个处理器\n256GB 内存\n每个处理器 1MB L2 cache\n64B cache line\n",[1001,3356,3354],{"__ignoreMap":1045},[1019,3358,3360],{"id":3359},"朴素目录每条内存行都放一个-sharing-vector","朴素目录：每条内存行都放一个 sharing vector",[981,3362,3363],{},"128 个处理器意味着每条内存行要一个 128-bit sharing vector：",[1037,3365,3368],{"className":3366,"code":3367,"language":1042},[1040],"128 bit = 16 bytes\n",[1001,3369,3367],{"__ignoreMap":1045},[981,3371,3372],{},"再加 3 bit 状态，约等于 16B。",[981,3374,3375],{},"每条 cache line 是 64B，所以目录开销是：",[1037,3377,3380],{"className":3378,"code":3379,"language":1042},[1040],"16 \u002F 64 = 0.25 = 25%\n",[1001,3381,3379],{"__ignoreMap":1045},[981,3383,3384],{},"256GB 内存对应的目录开销就是：",[1037,3386,3389],{"className":3387,"code":3388,"language":1042},[1040],"0.25 × 256GB = 64GB\n",[1001,3390,3388],{"__ignoreMap":1045},[981,3392,3393],{},"也就是说，光目录就要 64GB，太大了。课件给出的计算正是：128 位共享向量加状态约 16 字节，每行 16\u002F64 = 25%，总计 64GB 内存开销。",[1016,3395],{},[1019,3397,3399],{"id":3398},"解决方案cached-directories","解决方案：Cached Directories",[981,3401,3402],{},"观察：不是所有内存行都会同时被 cache。",[981,3404,3405],{},"整个系统一共有：",[1037,3407,3410],{"className":3408,"code":3409,"language":1042},[1040],"128 个处理器 × 每个 1MB cache = 128MB cache\n",[1001,3411,3409],{"__ignoreMap":1045},[981,3413,3414],{},"如果 cache line 是 64B，那么最多实际被缓存的行数是：",[1037,3416,3419],{"className":3417,"code":3418,"language":1042},[1040],"128MB \u002F 64B = 2M lines\n",[1001,3420,3418],{"__ignoreMap":1045},[981,3422,3423,3424,3427],{},"所以可以只给 ",[1012,3425,3426],{},"活跃缓存行"," 建目录，而不是给所有内存行都建目录。",[981,3429,3430,3431,1091],{},"这就叫 ",[1012,3432,3433],{},"cached directory",[981,3435,3436],{},"但是这样目录项需要额外保存 tag，因为它不是固定跟着每条内存行放了。",[981,3438,3439],{},"每个活跃 cache line 的目录开销大约是：",[1037,3441,3444],{"className":3442,"code":3443,"language":1042},[1040],"tag 8B + directory 16B = 24B\n24 \u002F 64 = 37.5%\n",[1001,3445,3443],{"__ignoreMap":1045},[981,3447,3448],{},"但总量只对应 2M 条活跃行：",[1037,3450,3453],{"className":3451,"code":3452,"language":1042},[1040],"0.375 × 2M × 64B = 768KB\n",[1001,3454,3452],{"__ignoreMap":1045},[981,3456,3457],{},"所以总开销从 64GB 降到约 768KB。课件也给出这个结论：只维护 actively cached lines 时，总开销约 768KB。",[1016,3459],{},[985,3461,3463],{"id":3462},"第-60-页过渡页缓存未命中的第四个-c","第 60 页：过渡页：缓存未命中的第四个 C",[981,3465,3466],{},"这一页基本是章节过渡：",[1037,3468,3471],{"className":3469,"code":3470,"language":1042},[1040],"The Fourth Cache Miss\n缓存未命中的第四个 C\n",[1001,3472,3470],{"__ignoreMap":1045},[981,3474,3475],{},"前面你学过传统 3C：",[1037,3477,3480],{"className":3478,"code":3479,"language":1042},[1040],"Compulsory miss\nCapacity miss\nConflict miss\n",[1001,3481,3479],{"__ignoreMap":1045},[981,3483,3484],{},"现在多处理器系统中又出现一类新的 miss：",[1037,3486,3489],{"className":3487,"code":3488,"language":1042},[1040],"Coherence miss\n",[1001,3490,3488],{"__ignoreMap":1045},[981,3492,3493,3494,1091],{},"它不是因为 cache 太小，也不是因为映射冲突，而是因为 ",[1012,3495,3496],{},"别的处理器的一致性操作让你的 cache line 失效了",[1016,3498],{},[985,3500,3502],{"id":3501},"第-61-页smp-性能","第 61 页：SMP 性能",[981,3504,3505],{},[3227,3506],{"alt":3227,"src":3507},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-02.png",[981,3509,3510],{},"SMP = Symmetric Multiprocessor，对称多处理器。",[981,3512,3513],{},"这一页讲：多处理器里的 cache 性能不只取决于单核 cache miss，还取决于处理器之间的通信。",[1019,3515,3517],{"id":3516},"单处理器-cache-miss-流量","单处理器 cache miss 流量",[981,3519,3520],{},"这是传统 cache miss：",[1037,3522,3525],{"className":3523,"code":3524,"language":1042},[1040],"第一次访问没有\ncache 容量不够\ncache 映射冲突\n",[1001,3526,3524],{"__ignoreMap":1045},[981,3528,3529],{},"这些就是 3C 里面的内容。",[1016,3531],{},[1019,3533,3534],{"id":3534},"通信造成的流量",[981,3536,3537],{},"多核程序中，处理器之间会通过共享变量通信。",[981,3539,3131],{},[1037,3541,3544],{"className":3542,"code":3543,"language":1042},[1040],"P0 写 flag = 1\nP1 读 flag\n",[1001,3545,3543],{"__ignoreMap":1045},[981,3547,3548],{},"这种通信会导致：",[1037,3550,3553],{"className":3551,"code":3552,"language":1042},[1040],"invalidate\ncache miss\n数据在不同 cache 之间转移\n",[1001,3554,3552],{"__ignoreMap":1045},[981,3556,3557],{},"这部分流量是单核程序没有的。",[1016,3559],{},[1019,3561,3563],{"id":3562},"coherence-miss","Coherence Miss",[981,3565,3566],{},"课件把它叫：",[1037,3568,3570],{"className":3569,"code":3488,"language":1042},[1040],[1001,3571,3488],{"__ignoreMap":1045},[981,3573,3574],{},"也叫：",[1037,3576,3579],{"className":3577,"code":3578,"language":1042},[1040],"Communication miss\n",[1001,3580,3578],{"__ignoreMap":1045},[981,3582,3583],{},"它是传统 3C 之外的第四类 cache miss。课件第 61 页明确说，SMP 缓存性能包括单处理器 miss 流量和通信造成的流量，而 coherence miss 是 Compulsory、Capacity、Conflict 之外的第四类 miss。",[1016,3585],{},[985,3587,3589],{"id":3588},"第-62-页按-block-跟踪缓存一致性","第 62 页：按 block 跟踪缓存一致性",[981,3591,3592],{},[3227,3593],{"alt":3227,"src":3594},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-03.png",[981,3596,3597,3598,3601],{},"这一页是理解 ",[1012,3599,3600],{},"false sharing"," 的基础。",[981,3603,3604],{},"课件设定：",[1037,3606,3609],{"className":3607,"code":3608,"language":1042},[1040],"block 大小 = 32B\nProcessor 0 读写变量 X\nProcessor 1 读写变量 Y\nX 地址 = 4000\nY 地址 = 4012\n",[1001,3610,3608],{"__ignoreMap":1045},[981,3612,3293],{},[1037,3614,3617],{"className":3615,"code":3616,"language":1042},[1040],"4000 和 4012 虽然是不同变量，\n但它们落在同一个 32B cache block 里。\n",[1001,3618,3616],{"__ignoreMap":1045},[981,3620,3621],{},"因为一个 32B block 可能覆盖：",[1037,3623,3626],{"className":3624,"code":3625,"language":1042},[1040],"4000, 4004, 4008, 4012, 4016, ..., 4028\n",[1001,3627,3625],{"__ignoreMap":1045},[981,3629,3630],{},"所以：",[1037,3632,3635],{"className":3633,"code":3634,"language":1042},[1040],"X 和 Y 是不同 word\n但属于同一个 cache line\n",[1001,3636,3634],{"__ignoreMap":1045},[981,3638,3639,3640,3643],{},"Cache coherence 是按 ",[1012,3641,3642],{},"cache line\u002Fblock"," 管理的，不是按单个变量管理。",[981,3645,3646],{},"所以如果 P0 写 X：",[1037,3648,3651],{"className":3649,"code":3650,"language":1042},[1040],"P0 获得整个 block 的独占权\n",[1001,3652,3650],{"__ignoreMap":1045},[981,3654,3655],{},"这会导致 P1 里包含 Y 的那整个 block 被 invalid。",[981,3657,3658],{},"即使 P1 根本没有用 X，只是在用 Y，也会受影响。课件第 62 页正是用 X=4000、Y=4012、block=32B 来说明这个问题。",[1016,3660],{},[985,3662,3664],{"id":3663},"第-63-页干预-intervention","第 63 页：干预 Intervention",[981,3666,3667],{},[3227,3668],{"alt":3227,"src":3669},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-04.png",[981,3671,3672,3673,1091],{},"这一页讲的是：当一个 cache 里有最新数据，而主存是旧的时，另一个处理器来读，",[1012,3674,3675],{},"不能让主存直接回答",[981,3677,3678],{},"图里有：",[1037,3680,3683],{"className":3681,"code":3682,"language":1042},[1040],"CPU-Memory Bus\nA 200\nA 100\n",[1001,3684,3682],{"__ignoreMap":1045},[981,3686,3687],{},"可以理解为：",[1037,3689,3692],{"className":3690,"code":3691,"language":1042},[1040],"某个 cache 中 A = 200，是最新值\nMemory 中 A = 100，是旧值\n",[1001,3693,3691],{"__ignoreMap":1045},[981,3695,3696],{},"现在另一个处理器请求读 A。",[981,3698,3699],{},"如果让 memory 返回 A=100，就错了。",[981,3701,3702],{},"所以拥有最新值的 cache 要“干预”：",[1037,3704,3707],{"className":3705,"code":3706,"language":1042},[1040],"看到总线上有人读 A\n发现自己有 A 的 modified copy\n于是阻止\u002F覆盖 memory 的旧响应\n把 A=200 提供出去\n",[1001,3708,3706],{"__ignoreMap":1045},[981,3710,3430,3711,1091],{},[1012,3712,2010],{},[981,3714,3715],{},"它的本质是：",[1037,3717,3720],{"className":3718,"code":3719,"language":1042},[1040],"当 cache 有最新脏数据时，\ncache 需要介入这次读请求，\n把最新数据提供给请求者。\n",[1001,3721,3719],{"__ignoreMap":1045},[981,3723,3724],{},"它和前面 Directory 的 “load with owner” 是同一个核心思想：如果某个 owner cache 有 modified line，读取者不能直接拿主存旧值，而要通过 owner 获得最新值；课件第 56 页也展示了 load with owner，需要 forward 和 acknowledge+value。",[1016,3726],{},[985,3728,3730],{"id":3729},"第-64-页伪共享-false-sharing","第 64 页：伪共享 False Sharing",[981,3732,3733],{},[3227,3734],{"alt":3227,"src":3735},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-05.png",[981,3737,3738],{},"这一页正式定义伪共享。",[1019,3740,3742],{"id":3741},"cache-line-含多个-word","Cache line 含多个 word",[981,3744,3745],{},"比如一条 cache line：",[1037,3747,3750],{"className":3748,"code":3749,"language":1042},[1040],"state | line addr | data0 | data1 | ... | dataN\n",[1001,3751,3749],{"__ignoreMap":1045},[981,3753,3754],{},"一个 cache line 里有很多 word。",[1016,3756],{},[1019,3758,3760],{"id":3759},"一致性是在-line-level-完成的","一致性是在 line-level 完成的",[981,3762,3763],{},"这句话非常关键：",[1037,3765,3768],{"className":3766,"code":3767,"language":1042},[1040],"Cache coherence 是按 cache line 管理，\n不是按 word 管理。\n",[1001,3769,3767],{"__ignoreMap":1045},[981,3771,3772],{},"所以硬件看到的是：",[1037,3774,3777],{"className":3775,"code":3776,"language":1042},[1040],"这一整行有没有被别人写？\n",[1001,3778,3776],{"__ignoreMap":1045},[981,3780,3781],{},"而不是：",[1037,3783,3786],{"className":3784,"code":3785,"language":1042},[1040],"这一行里的哪个具体 word 被写？\n",[1001,3787,3785],{"__ignoreMap":1045},[981,3789,3790],{},"课件也明确说：Cache line 包含多个字，cache coherence 是在 line-level 而不是 word-level 完成的。",[1016,3792],{},[1019,3794,3795],{"id":3795},"伪共享发生条件",[981,3797,1672],{},[1037,3799,3802],{"className":3800,"code":3801,"language":1042},[1040],"M1 写 word_i\nM2 写 word_k\ni ≠ k\n但 word_i 和 word_k 在同一个 cache line\n",[1001,3803,3801],{"__ignoreMap":1045},[981,3805,3806],{},"从程序角度看：",[1037,3808,3811],{"className":3809,"code":3810,"language":1042},[1040],"两个处理器写的是不同变量，没有真正共享同一个变量。\n",[1001,3812,3810],{"__ignoreMap":1045},[981,3814,3815],{},"但从硬件角度看：",[1037,3817,3820],{"className":3818,"code":3819,"language":1042},[1040],"它们写的是同一条 cache line。\n",[1001,3821,3819],{"__ignoreMap":1045},[981,3823,3824],{},"于是它们会不断让对方的 cache line 失效。",[981,3826,3827,3828,1091],{},"这就是 ",[1012,3829,3600],{},[1016,3831],{},[985,3833,3835],{"id":3834},"第-65-页跟踪-cache-block-coherency","第 65 页：跟踪 Cache Block Coherency",[981,3837,3838],{},[3227,3839],{"alt":3227,"src":3840},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-06.png",[981,3842,3843],{},"这一页总结第 62～64 页的现象。",[1019,3845,3847],{"id":3846},"两个-cache-之间会出现-ping-pong","两个 cache 之间会出现 ping-pong",[981,3849,1672],{},[1037,3851,3854],{"className":3852,"code":3853,"language":1042},[1040],"P0 反复写 X\nP1 反复写 Y\n",[1001,3855,3853],{"__ignoreMap":1045},[981,3857,3858],{},"X 和 Y 不同，但在同一个 cache line。",[981,3860,3861],{},"那么会出现：",[1037,3863,3866],{"className":3864,"code":3865,"language":1042},[1040],"P0 写 X -> P1 的整行失效\nP1 写 Y -> P0 的整行失效\nP0 再写 X -> P1 又失效\nP1 再写 Y -> P0 又失效\n",[1001,3867,3865],{"__ignoreMap":1045},[981,3869,3870],{},"这条 cache line 就在两个 cache 之间来回“弹来弹去”。",[981,3872,3873],{},"课件称之为：",[1037,3875,3878],{"className":3876,"code":3877,"language":1042},[1040],"ping-pong effect\n",[1001,3879,3877],{"__ignoreMap":1045},[981,3881,3882],{},"即使两个处理器访问的是不相交变量，也会出现。课件第 65 页明确说，两个缓存之间会发生 ping-pong effect，即使处理器访问的是不相交变量，这就是 false sharing。",[1016,3884],{},[1019,3886,3888],{"id":3887},"如何预防","如何预防？",[981,3890,3891],{},"核心方法是：",[1037,3893,3896],{"className":3894,"code":3895,"language":1042},[1040],"让不同处理器频繁写的数据不要落在同一个 cache line。\n",[1001,3897,3895],{"__ignoreMap":1045},[981,3899,3900],{},"常见办法：",[1037,3902,3905],{"className":3903,"code":3904,"language":1042},[1040],"加 padding\n按 cache line 对齐\n每个线程的数据分开放到不同 cache line\n",[1001,3906,3904],{"__ignoreMap":1045},[981,3908,1769],{},[1037,3910,3913],{"className":3911,"code":3912,"language":1497,"meta":1045},[1495],"\u002F\u002F 容易 false sharing\ndouble sum[NUM_THREADS];\n\n\u002F\u002F 更安全：让每个线程隔开一个 cache line\ndouble sum[NUM_THREADS][CACHE_LINE_SIZE \u002F sizeof(double)];\n",[1001,3914,3912],{"__ignoreMap":1045},[1016,3916],{},[985,3918,3920],{"id":3919},"第-66-页还记得-3c-吗","第 66 页：还记得 3C 吗？",[981,3922,3923],{},"这一页复习传统三类 cache miss。",[1019,3925,3927],{"id":3926},"compulsory-miss","Compulsory Miss",[981,3929,3930],{},"也叫 cold-start miss。",[981,3932,3168],{},[1037,3934,3937],{"className":3935,"code":3936,"language":1042},[1040],"第一次访问某个 block，cache 里肯定没有。\n",[1001,3938,3936],{"__ignoreMap":1045},[981,3940,1425],{},[1037,3942,3945],{"className":3943,"code":3944,"language":1042},[1040],"不可完全避免；\n长时间运行程序中占比通常较小。\n",[1001,3946,3944],{"__ignoreMap":1045},[981,3948,3949],{},"解决办法之一：",[1037,3951,3954],{"className":3952,"code":3953,"language":1042},[1040],"增大 block size\n",[1001,3955,3953],{"__ignoreMap":1045},[981,3957,3958],{},"但代价是：",[1037,3960,3963],{"className":3961,"code":3962,"language":1042},[1040],"miss penalty 变大；\nblock 太大还可能增加 miss rate。\n",[1001,3964,3962],{"__ignoreMap":1045},[981,3966,3967],{},"课件也这么总结：Compulsory 是第一次访问，解决方法可以是增加 block size，但会增加 miss penalty，过大还会增加 miss rate。",[1016,3969],{},[1019,3971,3973],{"id":3972},"capacity-miss","Capacity Miss",[981,3975,3168],{},[1037,3977,3980],{"className":3978,"code":3979,"language":1042},[1040],"cache 总容量不够，\n即使 fully associative + 完美替换策略，也装不下程序需要的所有 block。\n",[1001,3981,3979],{"__ignoreMap":1045},[981,3983,3984],{},"解决办法：",[1037,3986,3989],{"className":3987,"code":3988,"language":1042},[1040],"增加 cache size\n",[1001,3990,3988],{"__ignoreMap":1045},[981,3992,3993],{},"代价：",[1037,3995,3998],{"className":3996,"code":3997,"language":1042},[1040],"可能增加访问时间。\n",[1001,3999,3997],{"__ignoreMap":1045},[1016,4001],{},[1019,4003,4005],{"id":4004},"conflict-miss","Conflict Miss",[981,4007,3168],{},[1037,4009,4012],{"className":4010,"code":4011,"language":1042},[1040],"cache 总容量够，\n但多个内存块映射到同一个 cache 位置，\n互相挤掉。\n",[1001,4013,4011],{"__ignoreMap":1045},[981,4015,3984],{},[1037,4017,4020],{"className":4018,"code":4019,"language":1042},[1040],"增加 cache size\n增加 associativity\n改进替换策略，例如 LRU\n",[1001,4021,4019],{"__ignoreMap":1045},[981,4023,4024],{},"课件把这些都归纳在第 66 页。",[1016,4026],{},[985,4028,4030],{"id":4029},"第-67-页第四个-ccoherence-misses","第 67 页：第四个 C：Coherence Misses",[981,4032,4033],{},"这一页引出重点：多处理器里还有第四种 miss。",[1019,4035,4037],{"id":4036},"coherence-miss-是什么","Coherence Miss 是什么？",[981,4039,4040],{},"定义：",[1037,4042,4045],{"className":4043,"code":4044,"language":1042},[1040],"由于其他处理器的一致性通信导致的 cache miss。\n",[1001,4046,4044],{"__ignoreMap":1045},[981,4048,3131],{},[1037,4050,4053],{"className":4051,"code":4052,"language":1042},[1040],"P0 有 A\nP1 写 A\nP0 的 A 被 invalid\nP0 下次再读 A，miss\n",[1001,4054,4052],{"__ignoreMap":1045},[981,4056,4057],{},"这个 miss 不是因为 cache 小，也不是因为映射冲突，而是因为一致性协议让它失效。",[981,4059,4060],{},"课件第 67 页明确说，coherence misses 是由于与其他处理器的一致性通信而导致的 miss，也叫 communication misses。",[1016,4062],{},[1019,4064,4066],{"id":4065},"为什么也叫-communication-miss","为什么也叫 Communication Miss？",[981,4068,4069],{},"因为它本质上来自处理器之间的数据移动。",[981,4071,3131],{},[1037,4073,4076],{"className":4074,"code":4075,"language":1042},[1040],"P0 写完数据\nP1 要读这个数据\n",[1001,4077,4075],{"__ignoreMap":1045},[981,4079,4080],{},"数据必须从 P0 cache \u002F memory 转移给 P1。",[981,4082,4083],{},"这就是并行程序里的通信。",[1016,4085],{},[1019,4087,4089],{"id":4088},"coherence-miss-可能很严重","Coherence Miss 可能很严重",[981,4091,4092],{},"在一些并行程序中，如果多个处理器频繁共享或伪共享数据：",[1037,4094,4097],{"className":4095,"code":4096,"language":1042},[1040],"不断 invalid\n不断 miss\n不断重新取数据\n",[1001,4098,4096],{"__ignoreMap":1045},[981,4100,4101],{},"coherence miss 可能会成为主要性能瓶颈。",[981,4103,4104],{},"课件也说，在一些并行程序中，coherence misses 可能主导总的 miss。",[1016,4106],{},[978,4108,4109],{},[981,4110,4111],{},[1012,4112,4113],{},"Coherence 是按 cache line 维护的，不是按变量维护的；所以即使两个处理器访问不同变量，只要它们落在同一个 cache line，也可能互相 invalid，产生 false sharing 和 coherence miss。",[981,4115,4116],{},"下面这组页的主线是：",[981,4118,4119],{},[1012,4120,4121],{},"Coherence Miss → True\u002FFalse Sharing → 伪共享如何影响性能 → 如何避免 → 进入 Memory Consistency Model。",[1016,4123],{},[985,4125,4127],{"id":4126},"第-68-页一致性缺失-coherency-misses","第 68 页：一致性缺失 Coherency Misses",[981,4129,4130],{},[3227,4131],{"alt":3227,"src":4132},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-07.png",[981,4134,4135,4136,4139],{},"这一页把 ",[1012,4137,4138],{},"coherence miss"," 分成两类：",[1037,4141,4144],{"className":4142,"code":4143,"language":1042},[1040],"Coherence miss\n├── True sharing miss   真共享缺失\n└── False sharing miss  伪共享缺失\n",[1001,4145,4143],{"__ignoreMap":1045},[1410,4147,4149],{"id":4148},"真共享缺失-true-sharing-miss","真共享缺失 True sharing miss",[981,4151,4152,4153],{},"真共享的意思是：",[1012,4154,4155],{},"两个处理器真的在访问同一个变量 \u002F 同一个 word。",[981,4157,1769],{},[1037,4159,4162],{"className":4160,"code":4161,"language":1042},[1040],"P1 写 X = 10\nP2 后面读 X\n",[1001,4163,4161],{"__ignoreMap":1045},[981,4165,4166],{},"P1 写 X 时，会让 P2 cache 里的 X 失效。",[981,4168,4169],{},"P2 之后再读 X，就会 miss。",[981,4171,4172],{},"这个 miss 是“合理的”，因为 P2 确实需要 P1 写过的新值。",[981,4174,4175],{},"所以真共享缺失的本质是：",[1037,4177,4180],{"className":4178,"code":4179,"language":1042},[1040],"不同处理器真的通过同一个数据通信。\n",[1001,4181,4179],{"__ignoreMap":1045},[1016,4183],{},[1410,4185,4187],{"id":4186},"伪共享缺失-false-sharing-miss","伪共享缺失 False sharing miss",[981,4189,4190,4191],{},"伪共享的意思是：",[1012,4192,4193],{},"两个处理器访问的是不同变量，但这些变量刚好在同一个 cache line 里。",[981,4195,1769],{},[1037,4197,4200],{"className":4198,"code":4199,"language":1042},[1040],"同一个 cache line 里有 X 和 Y\n\nP1 只写 X\nP2 只写 Y\n",[1001,4201,4199],{"__ignoreMap":1045},[981,4203,4204,4205,4208],{},"从程序逻辑看，P1 和 P2 没有共享同一个变量。\n但是硬件的一致性协议是按 ",[1012,4206,4207],{},"cache line"," 管理的，不是按单个变量管理的。",[981,4210,4211],{},"所以 P1 写 X 时，会让 P2 包含 Y 的整条 cache line 失效。",[981,4213,4214],{},"P2 之后访问 Y，也会 miss。",[981,4216,4217],{},"这个 miss 就是伪共享缺失。",[981,4219,1399],{},[1037,4221,4224],{"className":4222,"code":4223,"language":1042},[1040],"真共享：别人改的正是我要用的数据。\n伪共享：别人改的不是我要用的数据，但因为在同一 cache line，我也被误伤。\n",[1001,4225,4223],{"__ignoreMap":1045},[1016,4227],{},[1019,4229,4231],{"id":4230},"第-69-页例子真伪共享与命中","第 69 页：例子：真伪共享与命中",[981,4233,4234],{},[3227,4235],{"alt":3227,"src":4236},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-08.png",[981,4238,4239],{},"这一页用一个表格追踪两个处理器 P1、P2 的 cache 状态。",[981,4241,4242,4243,4246],{},"表里的 ",[1001,4244,4245],{"code":4245},"(X, Y)"," 表示：",[1037,4248,4251],{"className":4249,"code":4250,"language":1042},[1040],"X 和 Y 在同一个 cache block \u002F cache line 里。\n",[1001,4252,4250],{"__ignoreMap":1045},[981,4254,4255,4256,1091],{},"所以 cache 状态不是单独针对 X 或 Y，而是针对整块 ",[1001,4257,4245],{"code":4245},[981,4259,4260],{},"表中反复出现：",[1037,4262,4265],{"className":4263,"code":4264,"language":1042},[1040],"P1 Cache State: Modified(X, Y)\nP2 Cache State: Invalid(X, Y)\n",[1001,4266,4264],{"__ignoreMap":1045},[981,4268,3168],{},[1037,4270,4273],{"className":4271,"code":4272,"language":1042},[1040],"P1 拿到了整个 cache line (X, Y) 的写权限；\nP2 中这一整行都被 invalid。\n",[1001,4274,4272],{"__ignoreMap":1045},[981,4276,4277],{},"即使 P2 只关心 Y，P1 只关心 X，也会发生整行失效。",[1016,4279],{},[1410,4281,4282],{"id":4282},"表中几种典型情况",[4284,4285,4287],"h5",{"id":4286},"情况-1p1-写-x","情况 1：P1 写 X",[981,4289,4290,4291,4293],{},"P1 写 X 时，它必须获得整个 ",[1001,4292,4245],{"code":4245}," block 的独占权限：",[1037,4295,4298],{"className":4296,"code":4297,"language":1042},[1040],"P1: Modified(X, Y)\nP2: Invalid(X, Y)\n",[1001,4299,4297],{"__ignoreMap":1045},[981,4301,4302],{},"解释栏写的是：",[1037,4304,4307],{"className":4305,"code":4306,"language":1042},[1040],"P1 Invalidates block (X, Y) in P2\n",[1001,4308,4306],{"__ignoreMap":1045},[981,4310,4311,4312,4315],{},"也就是说，P1 写 X 会让 P2 的整个 ",[1001,4313,4314],{"code":4314},"(X,Y)"," block 失效。",[981,4317,4318,4319,1091],{},"如果 P2 后面要读 Y，那么 P2 会 miss。\n但 P2 读的是 Y，不是 P1 刚写的 X，所以这是 ",[1012,4320,4321],{},"false sharing miss",[1016,4323],{},[4284,4325,4327],{"id":4326},"情况-2p2-读取这个-block","情况 2：P2 读取这个 block",[981,4329,4330],{},"表里有：",[1037,4332,4335],{"className":4333,"code":4334,"language":1042},[1040],"P1: Shared(X, Y)\nP2: Shared(X, Y)\nExplanation: Write-back & Copy block from P1 to P2\n",[1001,4336,4334],{"__ignoreMap":1045},[981,4338,3168],{},[1037,4340,4343],{"className":4341,"code":4342,"language":1042},[1040],"P1 原来有最新的 Modified block；\nP2 想读；\nP1 必须把最新 block 提供出来；\n最后两边都变成 Shared。\n",[1001,4344,4342],{"__ignoreMap":1045},[981,4346,4347],{},"如果 P2 读取的是 P1 刚写过的 X，那是真共享。",[981,4349,4350],{},"如果 P2 只是读取 Y，那就是伪共享造成的数据搬运。",[1016,4352],{},[4284,4354,4356],{"id":4355},"情况-3p1-和-p2-交替写不同-word","情况 3：P1 和 P2 交替写不同 word",[981,4358,4359],{},"如果 P1 写 X，P2 写 Y，P1 再写 X，P2 再写 Y：",[1037,4361,4364],{"className":4362,"code":4363,"language":1042},[1040],"P1 写 X -> P2 的 (X,Y) invalid\nP2 写 Y -> P1 的 (X,Y) invalid\nP1 写 X -> P2 的 (X,Y) invalid\n...\n",[1001,4365,4363],{"__ignoreMap":1045},[981,4367,4368,4369,1091],{},"这条 cache line 会在 P1 和 P2 之间来回移动，叫 ",[1012,4370,4371],{},"ping-pong",[981,4373,4374],{},"这就是伪共享最典型的性能问题。",[1016,4376],{},[1019,4378,4380],{"id":4379},"第-70-页4-核商业处理器工作负载的-miss-分解","第 70 页：4 核商业处理器工作负载的 miss 分解",[981,4382,4383],{},[3227,4384],{"alt":3227,"src":4385},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-09.png",[981,4387,4388],{},"这一页的柱状图把 miss 分成几类：",[1037,4390,4393],{"className":4391,"code":4392,"language":1042},[1040],"Instruction\nCapacity \u002F Conflict\nCold\nFalse Sharing\nTrue Sharing\n",[1001,4394,4392],{"__ignoreMap":1045},[981,4396,4397],{},"这张图想说明：",[978,4399,4400],{},[981,4401,4402],{},"在多核商业工作负载中，cache miss 不只是传统 3C miss，还包含 true sharing 和 false sharing。",[981,4404,4405],{},"传统单核只关心：",[1037,4407,4410],{"className":4408,"code":4409,"language":1042},[1040],"Cold miss\nCapacity miss\nConflict miss\n",[1001,4411,4409],{"__ignoreMap":1045},[981,4413,4414],{},"但多核还要看：",[1037,4416,4419],{"className":4417,"code":4418,"language":1042},[1040],"True sharing miss\nFalse sharing miss\n",[1001,4420,4418],{"__ignoreMap":1045},[981,4422,4423,4424,2335,4427,4430],{},"图里可以看到，",[1012,4425,4426],{},"True Sharing",[1012,4428,4429],{},"False Sharing"," 确实占了一部分 miss。尤其是商业负载，比如 OLTP、数据库、搜索引擎，会频繁访问共享数据结构，所以 coherence miss 不能忽略。",[1016,4432],{},[1019,4434,4436],{"id":4435},"第-71-页2-mib-缓存商业处理器工作负载","第 71 页：2 MiB 缓存商业处理器工作负载",[981,4438,4439],{},[3227,4440],{"alt":3227,"src":4441},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-10.png",[981,4443,4444],{},"这一页和第 70 页类似，但强调的是在较大 cache 配置下，多核工作负载的 miss 构成。",[981,4446,4447],{},"重点不是记住具体柱子数值，而是理解趋势：",[1037,4449,4452],{"className":4450,"code":4451,"language":1042},[1040],"cache 变大后，\ncapacity\u002Fconflict miss 可能下降，\n但 true sharing \u002F false sharing 不一定消失。\n",[1001,4453,4451],{"__ignoreMap":1045},[981,4455,4456],{},"原因是：",[1037,4458,4461],{"className":4459,"code":4460,"language":1042},[1040],"coherence miss 不是因为 cache 太小，\n而是因为别的处理器写共享数据，导致你的副本失效。\n",[1001,4462,4460],{"__ignoreMap":1045},[981,4464,4465],{},"所以即使 cache 容量足够大，仍然可能因为多核通信产生 miss。",[1016,4467],{},[1019,4469,4471],{"id":4470},"第-72-页openmp-中的伪共享","第 72 页：OpenMP 中的伪共享",[981,4473,4474],{},[3227,4475],{"alt":3227,"src":4476},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-11.png",[981,4478,4479],{},"这一页给了一个计算 π 的 OpenMP 例子：",[1037,4481,4484],{"className":4482,"code":4483,"language":1497,"meta":1045},[1495],"double x, pi, sum[NUM_THREADS];\n\n#pragma omp parallel private(i, x)\n{\n    int id = omp_get_thread_num();\n\n    for (i = id, sum[id] = 0.0; i \u003C num_steps; i = i + NUM_THREADS) {\n        x = (i + 0.5) * step;\n        sum[id] += 4.0 \u002F (1.0 + x * x);\n    }\n}\n",[1001,4485,4483],{"__ignoreMap":1045},[981,4487,4488],{},"表面上看，每个线程都写自己的位置：",[1037,4490,4493],{"className":4491,"code":4492,"language":1042},[1040],"线程 0 写 sum[0]\n线程 1 写 sum[1]\n线程 2 写 sum[2]\n线程 3 写 sum[3]\n",[1001,4494,4492],{"__ignoreMap":1045},[981,4496,4497],{},"没有数据竞争。",[981,4499,4500],{},"但问题是：",[1037,4502,4505],{"className":4503,"code":4504,"language":1042},[1040],"double = 8 bytes\nsum[0] 和 sum[1] 在内存中相邻\n",[1001,4506,4504],{"__ignoreMap":1045},[981,4508,4509],{},"如果 cache line 是 64B，那么一条 cache line 可以放：",[1037,4511,4514],{"className":4512,"code":4513,"language":1042},[1040],"64 \u002F 8 = 8 个 double\n",[1001,4515,4513],{"__ignoreMap":1045},[981,4517,4518],{},"也就是说：",[1037,4520,4523],{"className":4521,"code":4522,"language":1042},[1040],"sum[0], sum[1], ..., sum[7]\n",[1001,4524,4522],{"__ignoreMap":1045},[981,4526,4527],{},"很可能在同一条 cache line 里。",[981,4529,4530,4531,4534,4535,4538,4539,4542,4543,4546],{},"于是线程 0 更新 sum",[1105,4532,4533],{},"0","，会让线程 1、2、3 所在 cache 的整条 line 失效；线程 1 更新 sum",[1105,4536,4537],{},"1","，又让线程 0 的整条 line 失效。课件也指出，",[1001,4540,4541],{"code":4541},"sum[0]"," 是 8 字节，",[1001,4544,4545],{"code":4545},"sum[1]"," 是相邻的 8 字节，如果块大小大于 8 字节，就会发生 false sharing。",[981,4548,4549],{},"所以这段程序的问题不是结果错，而是：",[1037,4551,4554],{"className":4552,"code":4553,"language":1042},[1040],"性能会很差。\n",[1001,4555,4553],{"__ignoreMap":1045},[1016,4557],{},[1019,4559,4561],{"id":4560},"第-73-页练习题避免伪共享","第 73 页：练习题：避免伪共享",[981,4563,4564],{},[3227,4565],{"alt":3227,"src":4566},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-12.png",[981,4568,4569],{},"代码变成：",[1037,4571,4574],{"className":4572,"code":4573,"language":1497,"meta":1045},[1495],"double x, pi, sum[10000];\n\n#pragma omp parallel private(i, x)\n{\n    int id = omp_get_thread_num(), fix = ________;\n\n    for (i = id, sum[id] = 0.0; i \u003C num_steps; i = i + NUM_THREADS) {\n        x = (i + 0.5) * step;\n        sum[id * fix] += 4.0 \u002F (1.0 + x * x);\n    }\n}\n",[1001,4575,4573],{"__ignoreMap":1045},[981,4577,3293,4578,4581],{},[1001,4579,4580],{"code":4580},"fix"," 取什么值可以避免 false sharing？",[981,4583,4584],{},"答案是：",[1037,4586,4589],{"className":4587,"code":4588,"language":1042},[1040],"YELLOW：Constant for size of blocks in doubles\n",[1001,4590,4588],{"__ignoreMap":1045},[981,4592,1893],{},[1037,4594,4597],{"className":4595,"code":4596,"language":1042},[1040],"fix = cache line 中能放多少个 double\n",[1001,4598,4596],{"__ignoreMap":1045},[981,4600,4601],{},"如果 cache line 是 64B，double 是 8B：",[1037,4603,4606],{"className":4604,"code":4605,"language":1042},[1040],"fix = 64 \u002F 8 = 8\n",[1001,4607,4605],{"__ignoreMap":1045},[981,4609,4610],{},"这样：",[1037,4612,4615],{"className":4613,"code":4614,"language":1042},[1040],"线程 0 写 sum[0]\n线程 1 写 sum[8]\n线程 2 写 sum[16]\n线程 3 写 sum[24]\n",[1001,4616,4614],{"__ignoreMap":1045},[981,4618,4619],{},"它们就落在不同 cache line 里，不会互相 invalid。",[981,4621,4622],{},"为什么不是 ORANGE？",[1037,4624,4627],{"className":4625,"code":4626,"language":1042},[1040],"ORANGE = block size in bytes\n",[1001,4628,4626],{"__ignoreMap":1045},[981,4630,4631,4632,4635],{},"如果直接用 64，间隔太大了。\n真正需要的是 ",[1012,4633,4634],{},"以 double 为单位的 cache line 大小","，所以是 YELLOW。",[1016,4637],{},[1019,4639,4641],{"id":4640},"第-74-页过渡页","第 74 页：过渡页",[981,4643,4644],{},[3227,4645],{"alt":3227,"src":4646},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-13.png",[1016,4648],{},[1019,4650,4652],{"id":4651},"第-75-页加速和缩放的类型","第 75 页：加速和缩放的类型",[981,4654,4655],{},[3227,4656],{"alt":3227,"src":4657},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-14.png",[981,4659,4660,4661,1091],{},"这一页讲 ",[1012,4662,4663],{},"scalability，可扩展性",[981,4665,4040],{},[1037,4667,4670],{"className":4668,"code":4669,"language":1042},[1040],"如果给机器增加 x 倍资源，\n性能也接近提高 x 倍，\n就叫可扩展性好。\n",[1001,4671,4669],{"__ignoreMap":1045},[981,4673,4674],{},"这里的资源通常是：",[1037,4676,4679],{"className":4677,"code":4678,"language":1042},[1040],"处理器数量\n内存容量\n互连带宽\n",[1001,4680,4678],{"__ignoreMap":1045},[981,4682,4683],{},"课件说，加入 x 倍资源后希望得到接近 x 倍的性能，也就是随着处理器数量增加，效率还能保持。",[981,4685,4686],{},"这一页还说，常见的可扩展性模型有两类：",[1037,4688,4691],{"className":4689,"code":4690,"language":1042},[1040],"Problem constrained scaling\nTime constrained scaling\n",[1001,4692,4690],{"__ignoreMap":1045},[1016,4694],{},[1019,4696,4698],{"id":4697},"第-76-页problem-constrained-scaling","第 76 页：Problem Constrained Scaling",[981,4700,4701],{},[3227,4702],{"alt":3227,"src":4703},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-15.png",[981,4705,4706,4707,1091],{},"这个也可以理解成 ",[1012,4708,4709],{},"强缩放 strong scaling",[981,4711,1425],{},[1037,4713,4716],{"className":4714,"code":4715,"language":1042},[1040],"问题规模固定；\n增加处理器数量；\n目标是减少执行时间。\n",[1001,4717,4715],{"__ignoreMap":1045},[981,4719,1769],{},[1037,4721,4724],{"className":4722,"code":4723,"language":1042},[1040],"同一个矩阵乘法任务\n1 个处理器要 100 秒\n10 个处理器希望接近 10 秒\n",[1001,4725,4723],{"__ignoreMap":1045},[981,4727,4728],{},"加速比定义为：",[1037,4730,4733],{"className":4731,"code":4732,"language":1042},[1040],"S = Time(1 processor) \u002F Time(p processors)\n",[1001,4734,4732],{"__ignoreMap":1045},[981,4736,1893],{},[1037,4738,4741],{"className":4739,"code":4740,"language":1042},[1040],"同一个任务，用 p 个处理器比用 1 个处理器快多少。\n",[1001,4742,4740],{"__ignoreMap":1045},[981,4744,4745],{},"这类缩放更难，因为问题规模固定后，处理器越多，每个处理器分到的工作越少，通信和同步开销占比会变大。",[1016,4747],{},[1019,4749,4751],{"id":4750},"第-77-页time-constrained-scaling","第 77 页：Time Constrained Scaling",[981,4753,4754],{},[3227,4755],{"alt":3227,"src":4756},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-16.png",[981,4758,4759,4760,1091],{},"这个接近 ",[1012,4761,4762],{},"弱缩放 weak scaling",[981,4764,1425],{},[1037,4766,4769],{"className":4767,"code":4768,"language":1042},[1040],"允许执行时间固定；\n增加处理器数量；\n目标是处理更大的问题。\n",[1001,4770,4768],{"__ignoreMap":1045},[981,4772,1769],{},[1037,4774,4777],{"className":4775,"code":4776,"language":1042},[1040],"1 个处理器 1 分钟处理 1GB 数据；\n10 个处理器 1 分钟希望处理 10GB 数据。\n",[1001,4778,4776],{"__ignoreMap":1045},[981,4780,4728],{},[1037,4782,4785],{"className":4783,"code":4784,"language":1042},[1040],"S = Work(p processors) \u002F Work(1 processor)\n",[1001,4786,4784],{"__ignoreMap":1045},[981,4788,1893],{},[1037,4790,4793],{"className":4791,"code":4792,"language":1042},[1040],"在相同时间内，多处理器能完成多少倍工作。\n",[1001,4794,4792],{"__ignoreMap":1045},[981,4796,4797],{},"这类缩放通常比强缩放容易，因为每个处理器仍然有足够多的工作，通信开销相对不那么显眼。",[1016,4799],{},[1019,4801,4803],{"id":4802},"第-78-页同步-synchronization","第 78 页：同步 Synchronization",[981,4805,4806],{},[3227,4807],{"alt":3227,"src":4808},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-17.png",[981,4810,4811],{},"这一页进入同步问题。",[981,4813,4814],{},"只要系统中存在并发进程，就需要同步，即使是单处理器系统也一样。课件把同步分成两类：生产者-消费者和互斥。",[1410,4816,4818],{"id":4817},"生产者-消费者-producer-consumer","生产者-消费者 Producer-Consumer",[981,4820,3168],{},[1037,4822,4825],{"className":4823,"code":4824,"language":1042},[1040],"生产者先产生数据；\n消费者必须等数据准备好之后才能使用。\n",[1001,4826,4824],{"__ignoreMap":1045},[981,4828,1769],{},[1037,4830,4833],{"className":4831,"code":4832,"language":1042},[1040],"P1 写 data\nP1 设置 flag = 1\n\nP2 看到 flag = 1\nP2 读取 data\n",[1001,4834,4832],{"__ignoreMap":1045},[981,4836,4837],{},"关键问题是：",[1037,4839,4842],{"className":4840,"code":4841,"language":1042},[1040],"P2 看到 flag = 1 时，data 是否一定已经可见？\n",[1001,4843,4841],{"__ignoreMap":1045},[981,4845,4846],{},"这会引出后面的 memory consistency model。",[1016,4848],{},[1410,4850,4852],{"id":4851},"互斥-mutual-exclusion","互斥 Mutual Exclusion",[981,4854,3168],{},[1037,4856,4859],{"className":4857,"code":4858,"language":1042},[1040],"同一时间只允许一个处理器使用共享资源。\n",[1001,4860,4858],{"__ignoreMap":1045},[981,4862,1769],{},[1037,4864,4867],{"className":4865,"code":4866,"language":1042},[1040],"一次只允许一个线程进入临界区；\n一次只允许一个人编辑文件。\n",[1001,4868,4866],{"__ignoreMap":1045},[981,4870,4871],{},"这通常通过 lock \u002F unlock 实现。",[1016,4873],{},[1019,4875,4877],{"id":4876},"第-79-页简单的生产者-消费者例子","第 79 页：简单的生产者-消费者例子",[981,4879,4880],{},[3227,4881],{"alt":3227,"src":4882},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-18.png",[981,4884,3678],{},[1037,4886,4889],{"className":4887,"code":4888,"language":1042},[1040],"Producer processor\nConsumer processor\nShared Memory: flag, data\n",[1001,4890,4888],{"__ignoreMap":1045},[981,4892,4893,4894,2335,4897,4900],{},"生产者和消费者都通过共享内存中的 ",[1001,4895,4896],{"code":4896},"flag",[1001,4898,4899],{"code":4899},"data"," 通信。",[981,4902,4903],{},"生产者的意图是：",[1037,4905,4908],{"className":4906,"code":4907,"language":1042},[1040],"先写 data；\n再写 flag = 1；\n告诉消费者数据准备好了。\n",[1001,4909,4907],{"__ignoreMap":1045},[981,4911,4912],{},"消费者的意图是：",[1037,4914,4917],{"className":4915,"code":4916,"language":1042},[1040],"不断读取 flag；\n如果 flag == 0，就继续等；\n如果 flag == 1，就读取 data。\n",[1001,4918,4916],{"__ignoreMap":1045},[981,4920,4921],{},"直觉上，我们希望：",[1037,4923,4926],{"className":4924,"code":4925,"language":1042},[1040],"消费者一旦看到 flag = 1，\n就一定能看到生产者写入的新 data。\n",[1001,4927,4925],{"__ignoreMap":1045},[981,4929,4930],{},"但这个直觉只在足够强的内存一致性模型下成立。",[981,4932,4933],{},"仅有 cache coherence 还不够，因为：",[1037,4935,4938],{"className":4936,"code":4937,"language":1042},[1040],"flag 和 data 是两个不同地址。\n",[1001,4939,4937],{"__ignoreMap":1045},[981,4941,4942],{},"Coherence 只保证单个地址的一致性，不能自动保证不同地址之间的顺序。",[1016,4944],{},[1019,4946,4948],{"id":4947},"第-80-页内存一致性模型-memory-consistency-model","第 80 页：内存一致性模型 Memory Consistency Model",[981,4950,4951],{},[3227,4952],{"alt":3227,"src":4953},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-19.png",[981,4955,4956],{},"这一页区分两个概念：",[1037,4958,4961],{"className":4959,"code":4960,"language":1042},[1040],"Cache coherence\nMemory consistency\n",[1001,4962,4960],{"__ignoreMap":1045},[1410,4964,4966],{"id":4965},"cache-coherence-解决什么","Cache coherence 解决什么？",[981,4968,4969,4970,1091],{},"它关注 ",[1012,4971,4972],{},"单个内存地址",[981,4974,4975],{},"例如地址 X：",[1037,4977,4980],{"className":4978,"code":4979,"language":1042},[1040],"P1 写 X = 1\nP2 读 X\nP3 写 X = 2\n",[1001,4981,4979],{"__ignoreMap":1045},[981,4983,4984],{},"Coherence 规定所有处理器对同一个地址 X 的读写应该看到合法顺序。",[1016,4986],{},[1410,4988,4990],{"id":4989},"memory-consistency-解决什么","Memory consistency 解决什么？",[981,4992,4969,4993,1091],{},[1012,4994,4995],{},"多个地址之间的顺序",[981,4997,1769],{},[1037,4999,5002],{"className":5000,"code":5001,"language":1042},[1040],"Producer 写 data\nProducer 写 flag\n\nConsumer 读 flag\nConsumer 读 data\n",[1001,5003,5001],{"__ignoreMap":1045},[981,5005,5006],{},"这里有两个地址：",[1037,5008,5011],{"className":5009,"code":5010,"language":1042},[1040],"data\nflag\n",[1001,5012,5010],{"__ignoreMap":1045},[981,5014,3293],{},[1037,5016,5019],{"className":5017,"code":5018,"language":1042},[1040],"Consumer 看到 flag = 1 时，\n是否一定能看到新的 data？\n",[1001,5020,5018],{"__ignoreMap":1045},[981,5022,5023],{},"这不是 coherence 单独能回答的问题。课件也说，内存一致性模型描述跨多个硬件线程时，load 指令可以返回哪些值；coherence 主要描述单个地址应该返回的合法值。",[1016,5025],{},[1019,5027,5029],{"id":5028},"第-81-页生产者-消费者代码","第 81 页：生产者-消费者代码",[981,5031,5032],{},[3227,5033],{"alt":3227,"src":5034},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-20.png",[981,5036,5037],{},"生产者代码：",[1037,5039,5042],{"className":5040,"code":5041,"language":1042},[1040],"sw xdata, (xdatap)\nli xflag, 1\nsw xflag, (xflagp)\n",[1001,5043,5041],{"__ignoreMap":1045},[981,5045,3168],{},[1037,5047,5050],{"className":5048,"code":5049,"language":1042},[1040],"先写 data；\n再把 flag 设为 1。\n",[1001,5051,5049],{"__ignoreMap":1045},[981,5053,5054],{},"消费者代码：",[1037,5056,5059],{"className":5057,"code":5058,"language":1042},[1040],"spin:\n    lw xflag, (xflagp)\n    beqz xflag, spin\n    lw xdata, (xdatap)\n",[1001,5060,5058],{"__ignoreMap":1045},[981,5062,3168],{},[1037,5064,5067],{"className":5065,"code":5066,"language":1042},[1040],"一直读 flag；\n如果 flag 是 0，就继续等；\n如果 flag 是 1，就读取 data。\n",[1001,5068,5066],{"__ignoreMap":1045},[981,5070,5071],{},"初始：",[1037,5073,5076],{"className":5074,"code":5075,"language":1042},[1040],"flag = 0\n",[1001,5077,5075],{"__ignoreMap":1045},[981,5079,5080],{},"这页问的问题是：",[1037,5082,5085],{"className":5083,"code":5084,"language":1042},[1040],"消费者看到 flag = 1 之前，\n生产者写入的 data 是否已经对消费者可见？\n",[1001,5086,5084],{"__ignoreMap":1045},[981,5088,5089,5090,5093],{},"在 ",[1012,5091,5092],{},"顺序一致性 SC"," 下，答案是：应该可见。",[981,5095,5096],{},"但在弱内存模型下，可能出现：",[1037,5098,5101],{"className":5099,"code":5100,"language":1042},[1040],"flag = 1 已经被消费者看到；\ndata 的新值还没有对消费者可见。\n",[1001,5102,5100],{"__ignoreMap":1045},[981,5104,5105],{},"所以后面需要讨论 memory consistency 和 fence。",[1016,5107],{},[1019,5109,5111],{"id":5110},"第-82-页顺序一致性-sc","第 82 页：顺序一致性 SC",[981,5113,5114],{},[3227,5115],{"alt":3227,"src":5116},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-21.png",[981,5118,5119],{},"这一页给的是 Leslie Lamport 的经典定义。",[981,5121,5122],{},"简单翻译：",[978,5124,5125],{},[981,5126,5127],{},"一个系统是顺序一致的，如果任何执行结果都像是所有处理器的操作按照某个全局顺序依次执行；并且每个处理器自己的操作顺序仍然符合程序规定的顺序。课件原文也强调：每个处理器的操作要按照程序指定的顺序出现。",[981,5129,5130],{},"拆成两点：",[1410,5132,5133],{"id":5133},"存在一个全局顺序",[981,5135,5136],{},"所有处理器的内存操作可以排成一个队列：",[1037,5138,5141],{"className":5139,"code":5140,"language":1042},[1040],"P1 的某条 store\nP2 的某条 load\nP1 的另一条 store\nP3 的 load\n...\n",[1001,5142,5140],{"__ignoreMap":1045},[981,5144,5145],{},"系统表现得好像这些操作是一个一个发生的。",[1016,5147],{},[1410,5149,5150],{"id":5150},"每个处理器内部顺序不能乱",[981,5152,5153],{},"如果 P1 程序里是：",[1037,5155,5158],{"className":5156,"code":5157,"language":1042},[1040],"store data\nstore flag\n",[1001,5159,5157],{"__ignoreMap":1045},[981,5161,5162],{},"那么在全局顺序里，也必须是：",[1037,5164,5167],{"className":5165,"code":5166,"language":1042},[1040],"store data 在 store flag 前面\n",[1001,5168,5166],{"__ignoreMap":1045},[981,5170,5171],{},"不能反过来。",[981,5173,5174,5175,5178],{},"所以在生产者-消费者例子中，如果消费者看到 ",[1001,5176,5177],{"code":5177},"flag = 1","，那么按 SC 推理：",[1037,5180,5183],{"className":5181,"code":5182,"language":1042},[1040],"Producer: store data 发生在 store flag 前\nConsumer: load flag 发生在 load data 前\nConsumer 读到 flag = 1，说明 store flag 已经发生\n因此 store data 也已经发生\n",[1001,5184,5182],{"__ignoreMap":1045},[981,5186,5187],{},"所以消费者应该读到新 data。",[1016,5189],{},[1019,5191,5193],{"id":5192},"第-83-页生产者-消费者中的顺序关系","第 83 页：生产者-消费者中的顺序关系",[981,5195,5196],{},[3227,5197],{"alt":3227,"src":5198},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-22.png",[981,5200,5201],{},"这一页继续用生产者-消费者说明 SC 的直觉。",[981,5203,5204],{},"图里红、蓝箭头可以理解成不同处理器上的操作顺序。",[981,5206,5207],{},"生产者这边的顺序是：",[1037,5209,5212],{"className":5210,"code":5211,"language":1042},[1040],"写 data\n写 flag\n",[1001,5213,5211],{"__ignoreMap":1045},[981,5215,5216],{},"消费者这边的顺序是：",[1037,5218,5221],{"className":5219,"code":5220,"language":1042},[1040],"读 flag\n读 data\n",[1001,5222,5220],{"__ignoreMap":1045},[981,5224,5225],{},"SC 要求这两个本地顺序都不能被打乱。",[981,5227,5228],{},"因此正确逻辑应该是：",[1037,5230,5233],{"className":5231,"code":5232,"language":1042},[1040],"Producer 写 data\nProducer 写 flag = 1\nConsumer 读到 flag = 1\nConsumer 再读 data\n",[1001,5234,5232],{"__ignoreMap":1045},[981,5236,5237],{},"这样消费者读 data 时，应该能看到生产者写的数据。",[981,5239,5240],{},"但现实硬件为了性能可能会做优化，例如：",[1037,5242,5245],{"className":5243,"code":5244,"language":1042},[1040],"store buffer\nload\u002Fstore 重排序\n让不同地址的访存乱序完成\n",[1001,5246,5244],{"__ignoreMap":1045},[981,5248,5249],{},"这就可能破坏这种直觉顺序。",[1016,5251],{},[1019,5253,5255],{"id":5254},"第-84-页大多数真正的机器都不是-sc","第 84 页：大多数真正的机器都不是 SC",[981,5257,5258],{},[3227,5259],{"alt":3227,"src":5260},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-23.png",[981,5262,5263],{},"这一页非常重要。",[981,5265,5266],{},"它说：",[1037,5268,5271],{"className":5269,"code":5270,"language":1042},[1040],"大多数真实机器都不是 Sequential Consistency。\n",[1001,5272,5270],{"__ignoreMap":1045},[981,5274,5275],{},"课件明确提到，只有少数商业 ISA 要求 SC，x86 和 ARM 都不是 SC；使用 SC 会让简单机器变慢，或者需要复杂硬件来保持性能。",[981,5277,5278],{},"为什么？",[981,5280,5281],{},"因为现代处理器为了性能，会使用：",[1037,5283,5286],{"className":5284,"code":5285,"language":1042},[1040],"store buffer\n乱序执行\n非阻塞 cache\nload\u002Fstore 优化\n写合并\n",[1001,5287,5285],{"__ignoreMap":1045},[981,5289,5290],{},"这些优化会让内存操作对其他处理器可见的顺序和程序顺序不完全一致。",[981,5292,5293],{},"所以现实中需要：",[1037,5295,5298],{"className":5296,"code":5297,"language":1042},[1040],"fence\nmemory barrier\natomic 操作\nacquire \u002F release\nlock \u002F unlock\n",[1001,5299,5297],{"__ignoreMap":1045},[981,5301,5302],{},"来明确告诉硬件：",[1037,5304,5307],{"className":5305,"code":5306,"language":1042},[1040],"这里的顺序不能乱。\n",[1001,5308,5306],{"__ignoreMap":1045},[981,5310,5311],{},"对于生产者-消费者例子，通常要保证：",[1037,5313,5316],{"className":5314,"code":5315,"language":1042},[1040],"生产者：data 写入必须在 flag 写入之前对外可见；\n消费者：看到 flag 后，读取 data 不能被提前。\n",[1001,5317,5315],{"__ignoreMap":1045},[981,5319,5320],{},"否则就可能出现：",[1037,5322,5325],{"className":5323,"code":5324,"language":1042},[1040],"Consumer 看到 flag = 1\n但读到旧 data\n",[1001,5326,5324],{"__ignoreMap":1045},[1016,5328],{},[981,5330,5331,5332,5335,5336,5339],{},"下面这几页进入的是 ",[1012,5333,5334],{},"Memory Consistency Model，内存一致性模型","。它和前面 ",[1012,5337,5338],{},"cache coherence"," 不一样：",[1037,5341,5344],{"className":5342,"code":5343,"language":1042},[1040],"Cache coherence：管同一个地址的值是否一致。\nMemory consistency：管不同地址的读写顺序是否符合程序员预期。\n",[1001,5345,5343],{"__ignoreMap":1045},[981,5347,5348,5349,2335,5351,5353,5354,5356,5357,5359,5360,5362,5363,5365],{},"例如生产者-消费者里有两个地址：",[1001,5350,4899],{"code":4899},[1001,5352,4896],{"code":4896},"。\n即使 ",[1001,5355,4899],{"code":4899}," 自己是 coherent 的、",[1001,5358,4896],{"code":4896}," 自己也是 coherent 的，也不代表消费者看到 ",[1001,5361,5177],{"code":5177}," 时一定能看到新的 ",[1001,5364,4899],{"code":4899},"。这就是 memory consistency 要解决的问题。课件也明确区分了：coherence 描述单个内存地址能返回什么合法值，而 consistency model 描述跨多个硬件线程时 load 可以返回哪些值。",[1016,5367],{},[985,5369,5371],{"id":5370},"第-85-页store-buffer-optimization存储缓冲区优化","第 85 页：Store Buffer Optimization，存储缓冲区优化",[981,5373,5374],{},[3227,5375],{"alt":3227,"src":5376},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-24.png",[981,5378,5379,5380,5383],{},"这页讲的是为什么真实处理器很少严格按照 ",[1012,5381,5382],{},"SC 顺序一致性"," 来执行。",[981,5385,5386],{},"图中每个 CPU 和 shared memory 中间加了一个：",[1037,5388,5391],{"className":5389,"code":5390,"language":1042},[1040],"Store Buffer\n",[1001,5392,5390],{"__ignoreMap":1045},[981,5394,5395,5396],{},"它的作用是：",[1012,5397,5398],{},"CPU 执行 store 时，不必等这个写操作真正进入 cache \u002F memory \u002F 对其他处理器可见，而是先把写操作放进 store buffer，CPU 继续往后执行。",[981,5400,1769],{},[1037,5402,5405],{"className":5403,"code":5404,"language":1042},[1040],"CPU 执行：store X = 1\n",[1001,5406,5404],{"__ignoreMap":1045},[981,5408,5409],{},"没有 store buffer 时，CPU 可能要等：",[1037,5411,5414],{"className":5412,"code":5413,"language":1042},[1040],"写入 cache\n获得 cache line 独占权\n完成一致性协议\n其他 cache 副本失效\n",[1001,5415,5413],{"__ignoreMap":1045},[981,5417,5418],{},"这会很慢。",[981,5420,5421],{},"有 store buffer 后：",[1037,5423,5426],{"className":5424,"code":5425,"language":1042},[1040],"store X = 1 先进入 store buffer\nCPU 继续执行后面的指令\n稍后再慢慢把 X=1 写到 cache \u002F memory 系统中\n",[1001,5427,5425],{"__ignoreMap":1045},[981,5429,5430],{},"所以它的优点是：",[1037,5432,5435],{"className":5433,"code":5434,"language":1042},[1040],"减少 store 阻塞 CPU 的时间；\n隐藏 cache miss \u002F coherence 操作延迟；\n提高流水线性能。\n",[1001,5436,5434],{"__ignoreMap":1045},[981,5438,5439],{},"但是它带来的问题是：",[1037,5441,5444],{"className":5442,"code":5443,"language":1042},[1040],"本处理器以为自己已经写了；\n其他处理器暂时还看不到这个写。\n",[1001,5445,5443],{"__ignoreMap":1045},[981,5447,5448],{},"这正是 TSO 比 SC 更弱的根源。",[1016,5450],{},[985,5452,5454],{"id":5453},"第-86-页tso-例子","第 86 页：TSO 例子",[981,5456,5457],{},[3227,5458],{"alt":3227,"src":5459},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-25.png",[981,5461,5462,5463,1091],{},"这一页通常对应经典的 ",[1012,5464,5465],{},"Store Buffering litmus test",[981,5467,5468],{},"假设初始：",[1037,5470,5473],{"className":5471,"code":5472,"language":1042},[1040],"X = 0\nY = 0\n",[1001,5474,5472],{"__ignoreMap":1045},[981,5476,5477],{},"两个处理器执行：",[1037,5479,5482],{"className":5480,"code":5481,"language":1042},[1040],"P1:\nX = 1\nr1 = Y\n\nP2:\nY = 1\nr2 = X\n",[1001,5483,5481],{"__ignoreMap":1045},[981,5485,5486],{},"表格中的：",[1037,5488,5491],{"className":5489,"code":5490,"language":1042},[1040],"P1.x2 = P1 最后读到的 Y\nP2.x2 = P2 最后读到的 X\n",[1001,5492,5490],{"__ignoreMap":1045},[981,5494,5495],{},"结果表：",[1342,5497,5498,5514],{},[1345,5499,5500],{},[1348,5501,5502,5505,5508,5511],{},[1351,5503,5504],{},"P1.x2",[1351,5506,5507],{},"P2.x2",[1351,5509,5510],{},"SC",[1351,5512,5513],{},"TSO",[1361,5515,5516,5528,5538,5548],{},[1348,5517,5518,5520,5522,5525],{},[1366,5519,4533],{},[1366,5521,4533],{},[1366,5523,5524],{},"N",[1366,5526,5527],{},"Y",[1348,5529,5530,5532,5534,5536],{},[1366,5531,4533],{},[1366,5533,4537],{},[1366,5535,5527],{},[1366,5537,5527],{},[1348,5539,5540,5542,5544,5546],{},[1366,5541,4537],{},[1366,5543,4533],{},[1366,5545,5527],{},[1366,5547,5527],{},[1348,5549,5550,5552,5554,5556],{},[1366,5551,4537],{},[1366,5553,4537],{},[1366,5555,5527],{},[1366,5557,5527],{},[981,5559,5560],{},"最关键的是第一行：",[1037,5562,5565],{"className":5563,"code":5564,"language":1042},[1040],"P1.x2 = 0\nP2.x2 = 0\n",[1001,5566,5564],{"__ignoreMap":1045},[981,5568,5089,5569,5571,5572,5575,5576,5579,5580,5583,5584,5587],{},[1012,5570,5510],{}," 下不允许。\n因为 SC 要求所有处理器的内存操作能排成一个全局顺序，而且每个处理器自己的程序顺序不能乱。无论怎么排，只要 P1 读到 ",[1001,5573,5574],{"code":5574},"Y=0","，说明 P2 的 ",[1001,5577,5578],{"code":5578},"Y=1"," 还没发生；P2 又读到 ",[1001,5581,5582],{"code":5582},"X=0","，说明 P1 的 ",[1001,5585,5586],{"code":5586},"X=1"," 还没发生。这样会形成矛盾，所以 SC 不允许。",[981,5589,5590,5591,5593],{},"但在 ",[1012,5592,5513],{}," 下允许。原因是：",[1037,5595,5598],{"className":5596,"code":5597,"language":1042},[1040],"P1 的 X=1 先进入 P1 的 store buffer，还没被 P2 看到；\nP2 的 Y=1 先进入 P2 的 store buffer，还没被 P1 看到；\nP1 随后读 Y，看到旧值 0；\nP2 随后读 X，也看到旧值 0。\n",[1001,5599,5597],{"__ignoreMap":1045},[981,5601,5602],{},"所以 TSO 的核心是：",[1037,5604,5607],{"className":5605,"code":5606,"language":1042},[1040],"每个处理器可以先看到自己的 store；\n其他处理器稍后才看到这个 store。\n",[1001,5608,5606],{"__ignoreMap":1045},[981,5610,5611],{},"课件第 89 页也把 TSO 描述为：处理器可以在其他处理器之前看到自己的写操作，这是由 store buffer 引起的。",[1016,5613],{},[985,5615,5617],{"id":5616},"第-87-页强与弱内存一致性模型","第 87 页：强与弱内存一致性模型",[981,5619,5620],{},[3227,5621],{"alt":3227,"src":5622},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-26.png",[981,5624,5625],{},"这一页在讲不同 memory model 的强弱。",[1019,5627,5629],{"id":5628},"强内存模型-stronger-models","强内存模型 Stronger models",[981,5631,5632],{},"强模型提供更多顺序保证。",[981,5634,5635],{},"典型代表：",[1037,5637,5640],{"className":5638,"code":5639,"language":1042},[1040],"SC，Sequential Consistency\n",[1001,5641,5639],{"__ignoreMap":1045},[981,5643,5644],{},"它对程序员最友好，因为程序看起来像：",[1037,5646,5649],{"className":5647,"code":5648,"language":1042},[1040],"所有处理器的内存操作按某个全局顺序一个一个执行；\n每个处理器内部仍保持程序顺序。\n",[1001,5650,5648],{"__ignoreMap":1045},[981,5652,5653],{},"好处：",[1037,5655,5658],{"className":5656,"code":5657,"language":1042},[1040],"编程简单；\n推理简单；\n更接近直觉。\n",[1001,5659,5657],{"__ignoreMap":1045},[981,5661,5662],{},"坏处：",[1037,5664,5667],{"className":5665,"code":5666,"language":1042},[1040],"硬件更难做快；\n很多重排序优化不能随便使用；\n可能需要复杂硬件检测顺序违规。\n",[1001,5668,5666],{"__ignoreMap":1045},[981,5670,5671],{},"课件也指出，强模型提供更多 load\u002Fstore 顺序保证，因此 ISA 级编程模型更简单，但可能需要更多硬件来确保顺序。",[1016,5673],{},[1019,5675,5677],{"id":5676},"弱内存模型-weaker-models","弱内存模型 Weaker models",[981,5679,5680],{},"弱模型提供较少顺序保证。",[981,5682,5653],{},[1037,5684,5687],{"className":5685,"code":5686,"language":1042},[1040],"硬件更容易做高性能；\n允许 store buffer；\n允许 load\u002Fstore 重排序；\n允许更激进的乱序执行。\n",[1001,5688,5686],{"__ignoreMap":1045},[981,5690,5662],{},[1037,5692,5695],{"className":5693,"code":5694,"language":1042},[1040],"程序员或编译器必须显式加 fence；\n并发程序更难理解；\n不小心就会出现“flag 已经变了，但 data 还没看到”的问题。\n",[1001,5696,5694],{"__ignoreMap":1045},[981,5698,5699],{},"所以弱模型会提供额外指令：",[1037,5701,5704],{"className":5702,"code":5703,"language":1042},[1040],"fence\nmemory barrier\nacquire \u002F release\natomic operation\n",[1001,5705,5703],{"__ignoreMap":1045},[981,5707,5708],{},"让软件告诉硬件：",[1037,5710,5713],{"className":5711,"code":5712,"language":1042},[1040],"这里不能乱序。\n",[1001,5714,5712],{"__ignoreMap":1045},[1016,5716],{},[985,5718,5720],{"id":5719},"第-88-页生产者-消费者中的栅栏-fence","第 88 页：生产者-消费者中的栅栏 Fence",[981,5722,5723],{},[3227,5724],{"alt":3227,"src":5725},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-27.png",[978,5727,5728,5732,5742,5745,5750,5752,5756,5759,5762,5768,5770,5776,5779,5785,5787,5793,5796,5799,5805,5808,5814,5820,5823,5825,5829,5834,5837,5843,5845,5849,5851,5857,5863,5869,5872,5878,5881,5887,5890,5896,5898,5902,5904,5910,5915,5921,5923,5929,5932,5938,5941,5943,5947,5950,5955,5958,5964,5967,5969,5972,5977,5980],{},[1019,5729,5731],{"id":5730},"fence","Fence",[981,5733,5734,5735,5737,5738,5741],{},"你可以把 ",[1012,5736,5730],{}," 理解成 CPU 里的一个“",[1012,5739,5740],{},"禁止越线标志 \u002F 栅栏","”。",[981,5743,5744],{},"它不是数据，也不是锁，而是一条指令，作用是：",[981,5746,5747],{},[1012,5748,5749],{},"告诉 CPU：某些内存操作不能乱序，必须等前面的完成后，后面的才能继续。",[1016,5751],{},[1410,5753,5755],{"id":5754},"为什么需要-fence","为什么需要 fence？",[981,5757,5758],{},"先看生产者-消费者问题。",[981,5760,5761],{},"生产者想表达的是：",[1037,5763,5766],{"className":5764,"code":5765,"language":1042},[1040],"写 data\n写 flag = 1\n",[1001,5767,5765],{"__ignoreMap":1045},[981,5769,3168],{},[1037,5771,5774],{"className":5772,"code":5773,"language":1042},[1040],"我先把数据准备好，\n然后再告诉别人：数据好了。\n",[1001,5775,5773],{"__ignoreMap":1045},[981,5777,5778],{},"消费者想表达的是：",[1037,5780,5783],{"className":5781,"code":5782,"language":1042},[1040],"读 flag\n如果 flag == 1，再读 data\n",[1001,5784,5782],{"__ignoreMap":1045},[981,5786,3168],{},[1037,5788,5791],{"className":5789,"code":5790,"language":1042},[1040],"我先确认数据好了，\n然后再去读数据。\n",[1001,5792,5790],{"__ignoreMap":1045},[981,5794,5795],{},"按人的直觉，这肯定没问题。",[981,5797,5798],{},"但是 CPU 为了性能，可能会做优化：",[1037,5800,5803],{"className":5801,"code":5802,"language":1042},[1040],"写 data 先放进 store buffer，还没真正让别人看到；\n写 flag = 1 反而先被别人看到了。\n",[1001,5804,5802],{"__ignoreMap":1045},[981,5806,5807],{},"于是消费者可能看到：",[1037,5809,5812],{"className":5810,"code":5811,"language":1042},[1040],"flag = 1\n",[1001,5813,5811],{"__ignoreMap":1045},[981,5815,5816,5817,5819],{},"以为数据好了，结果读 ",[1001,5818,4899],{"code":4899}," 时读到的还是旧值。",[981,5821,5822],{},"这就出错了。",[1016,5824],{},[1410,5826,5828],{"id":5827},"fence-是干什么的","fence 是干什么的？",[981,5830,5831],{},[1012,5832,5833],{},"fence 就是阻止这种乱序或延迟可见。",[981,5835,5836],{},"它像一个栅栏：",[1037,5838,5841],{"className":5839,"code":5840,"language":1042},[1040],"前面的操作没完成，后面的操作不能越过 fence。\n",[1001,5842,5840],{"__ignoreMap":1045},[1016,5844],{},[1019,5846,5848],{"id":5847},"生产者这里的-fence-ww","生产者这里的 fence w,w",[981,5850,5037],{},[1037,5852,5855],{"className":5853,"code":5854,"language":1042},[1040],"sd xdata, (xdatap)     # 写 data\nli xflag, 1\nfence w,w             # 写-写栅栏\nsd xflag, (xflagp)     # 写 flag = 1\n",[1001,5856,5854],{"__ignoreMap":1045},[981,5858,5859,5862],{},[1001,5860,5861],{"code":5861},"fence w,w"," 的意思是：",[1037,5864,5867],{"className":5865,"code":5866,"language":1042},[1040],"前面的写操作，必须在后面的写操作之前完成。\n",[1001,5868,5866],{"__ignoreMap":1045},[981,5870,5871],{},"这里就是：",[1037,5873,5876],{"className":5874,"code":5875,"language":1042},[1040],"写 data 必须先对外可见；\n然后才能写 flag = 1。\n",[1001,5877,5875],{"__ignoreMap":1045},[981,5879,5880],{},"所以它防止这种错误：",[1037,5882,5885],{"className":5883,"code":5884,"language":1042},[1040],"flag = 1 已经被消费者看到，\n但 data 还没真正写出去。\n",[1001,5886,5884],{"__ignoreMap":1045},[981,5888,5889],{},"你可以把它理解成：",[1037,5891,5894],{"className":5892,"code":5893,"language":1042},[1040],"生产者先把饭做好，再挂出“饭好了”的牌子。\n不能牌子先挂出去，饭还没做好。\n",[1001,5895,5893],{"__ignoreMap":1045},[1016,5897],{},[1019,5899,5901],{"id":5900},"消费者这里的-fence-rr","消费者这里的 fence r,r",[981,5903,5054],{},[1037,5905,5908],{"className":5906,"code":5907,"language":1042},[1040],"spin:\n    ld xflag, (xflagp)     # 读 flag\n    beqz xflag, spin       # 如果 flag == 0，继续等\n    fence r,r              # 读-读栅栏\n    ld xdata, (xdatap)     # 读 data\n",[1001,5909,5907],{"__ignoreMap":1045},[981,5911,5912,5862],{},[1001,5913,5914],{"code":5914},"fence r,r",[1037,5916,5919],{"className":5917,"code":5918,"language":1042},[1040],"前面的读操作，必须在后面的读操作之前完成。\n",[1001,5920,5918],{"__ignoreMap":1045},[981,5922,5871],{},[1037,5924,5927],{"className":5925,"code":5926,"language":1042},[1040],"必须先真的读到 flag = 1；\n然后才能读 data。\n",[1001,5928,5926],{"__ignoreMap":1045},[981,5930,5931],{},"它防止 CPU 提前做这种事：",[1037,5933,5936],{"className":5934,"code":5935,"language":1042},[1040],"还没确认 flag，就提前把 data 读了。\n",[1001,5937,5935],{"__ignoreMap":1045},[981,5939,5940],{},"如果 data 被提前读取，可能读到旧值。",[1016,5942],{},[1019,5944,5946],{"id":5945},"这页到底在讲什么","这页到底在讲什么？",[981,5948,5949],{},"这页讲的是：",[981,5951,5952],{},[1012,5953,5954],{},"在弱内存模型下，CPU 可能为了性能打乱内存操作的可见顺序。为了让生产者-消费者程序正确，需要用 fence 强制关键顺序。",[981,5956,5957],{},"具体就是两个顺序：",[1037,5959,5962],{"className":5960,"code":5961,"language":1042},[1040],"生产者：\n写 data  →  写 flag\n\n消费者：\n读 flag  →  读 data\n",[1001,5963,5961],{"__ignoreMap":1045},[981,5965,5966],{},"fence 的作用就是保护这两个箭头不能被打乱。",[1016,5968],{},[1019,5970,5971],{"id":5971},"一句话总结",[981,5973,5974],{},[1012,5975,5976],{},"fence 就是内存操作之间的“红绿灯”：前面的读\u002F写没按要求完成，后面的读\u002F写不能先过去。",[981,5978,5979],{},"这页最核心就是：",[1037,5981,5984],{"className":5982,"code":5983,"language":1042},[1040],"生产者用 fence w,w：\n保证 data 先写出去，flag 后写出去。\n\n消费者用 fence r,r：\n保证先看到 flag，再去读 data。\n",[1001,5985,5983],{"__ignoreMap":1045},[981,5987,5988],{},"这页回到生产者-消费者例子。",[981,5990,5991],{},"生产者想做：",[1037,5993,5996],{"className":5994,"code":5995,"language":1042},[1040],"sd xdata, (xdatap)\nli xflag, 1\nfence w,w\nsd xflag, (xflagp)\n",[1001,5997,5995],{"__ignoreMap":1045},[981,5999,6000],{},"消费者想做：",[1037,6002,6005],{"className":6003,"code":6004,"language":1042},[1040],"spin:\n    ld xflag, (xflagp)\n    beqz xflag, spin\n    fence r,r\n    ld xdata, (xdatap)\n",[1001,6006,6004],{"__ignoreMap":1045},[981,6008,6009],{},"这里的关键是两个 fence。",[1019,6011,6013,6014],{"id":6012},"生产者端fence-ww","生产者端：",[1001,6015,5861],{"code":5861},[981,6017,3168],{},[1037,6019,6022],{"className":6020,"code":6021,"language":1042},[1040],"前面的写操作，必须在后面的写操作之前完成 \u002F 对外可见。\n",[1001,6023,6021],{"__ignoreMap":1045},[981,6025,6026],{},"对应这里就是：",[1037,6028,6031],{"className":6029,"code":6030,"language":1042},[1040],"写 data 必须早于写 flag。\n",[1001,6032,6030],{"__ignoreMap":1045},[981,6034,6035],{},"否则可能出现：",[1037,6037,6040],{"className":6038,"code":6039,"language":1042},[1040],"flag = 1 已经被消费者看到；\n但 data 的新值还没对消费者可见。\n",[1001,6041,6039],{"__ignoreMap":1045},[981,6043,6044],{},"这就违反生产者-消费者的语义。",[1016,6046],{},[1019,6048,6050,6051],{"id":6049},"消费者端fence-rr","消费者端：",[1001,6052,5914],{"code":5914},[981,6054,3168],{},[1037,6056,6058],{"className":6057,"code":5918,"language":1042},[1040],[1001,6059,5918],{"__ignoreMap":1045},[981,6061,6026],{},[1037,6063,6066],{"className":6064,"code":6065,"language":1042},[1040],"先读 flag；\n确认 flag = 1；\n再读 data。\n",[1001,6067,6065],{"__ignoreMap":1045},[981,6069,6070],{},"否则硬件可能为了性能提前读取 data，导致：",[1037,6072,6075],{"className":6073,"code":6074,"language":1042},[1040],"消费者提前读到了旧 data；\n之后才看到 flag = 1。\n",[1001,6076,6074],{"__ignoreMap":1045},[981,6078,6079],{},"所以这页的核心是：",[1037,6081,6084],{"className":6082,"code":6083,"language":1042},[1040],"生产者用 fence 保证 data 写在 flag 写之前；\n消费者用 fence 保证 flag 读在 data 读之前。\n",[1001,6085,6083],{"__ignoreMap":1045},[981,6087,6088,6089,2335,6091,6093],{},"课件第 88 页正是用 ",[1001,6090,5861],{"code":5861},[1001,6092,5914],{"code":5914}," 修正生产者-消费者顺序问题。",[1016,6095],{},[985,6097,6099],{"id":6098},"第-89-页内存一致性模型分类","第 89 页：内存一致性模型分类",[981,6101,6102],{},[3227,6103],{"alt":3227,"src":6104},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-28.png",[981,6106,6107],{},"这一页把常见 memory consistency model 分成几类。",[1019,6109,6111],{"id":6110},"scsequential-consistency","SC：Sequential Consistency",[981,6113,6114],{},"最强、最直观。",[1037,6116,6119],{"className":6117,"code":6118,"language":1042},[1040],"所有处理器看到一个统一的全局内存操作顺序；\n每个处理器自己的操作顺序保持程序顺序。\n",[1001,6120,6118],{"__ignoreMap":1045},[981,6122,6123],{},"优点是好理解，缺点是硬件实现成本高。",[1016,6125],{},[1019,6127,6129],{"id":6128},"tsototal-store-order","TSO：Total Store Order",[981,6131,6132],{},"比 SC 弱一点，但仍然算比较强。",[981,6134,6135],{},"TSO 允许的关键优化是：",[1037,6137,6140],{"className":6138,"code":6139,"language":1042},[1040],"store 进入 store buffer 后，\n后面的 load 可以先执行。\n",[1001,6141,6139],{"__ignoreMap":1045},[981,6143,6144],{},"也就是说，它允许一种重要重排序：",[1037,6146,6149],{"className":6147,"code":6148,"language":1042},[1040],"Store -> Load 可以表现得像被重排了。\n",[1001,6150,6148],{"__ignoreMap":1045},[981,6152,6153],{},"但是 TSO 仍然保持很多顺序，比如：",[1037,6155,6158],{"className":6156,"code":6157,"language":1042},[1040],"同一个处理器的 store 顺序通常仍然按程序顺序对外可见；\n其他处理器通常以相同顺序看到这些 store。\n",[1001,6159,6157],{"__ignoreMap":1045},[981,6161,6162],{},"课件列出的例子包括：",[1037,6164,6167],{"className":6165,"code":6166,"language":1042},[1040],"IBM-370 TSO\nx86 TSO\nSPARC TSO\nRISC-V RVTSO\n",[1001,6168,6166],{"__ignoreMap":1045},[1016,6170],{},[1019,6172,6174],{"id":6173},"弱的multi-copy-atomic-内存模型","弱的、multi-copy atomic 内存模型",[981,6176,6177],{},"multi-copy atomic 可以理解为：",[1037,6179,6182],{"className":6180,"code":6181,"language":1042},[1040],"一个处理器的写操作一旦对其他处理器可见，\n所有处理器看到这个写的顺序是一致的。\n",[1001,6183,6181],{"__ignoreMap":1045},[981,6185,6186],{},"也就是说，不同处理器不会对“别人写入的顺序”产生严重分歧。",[981,6188,6189],{},"课件举例：",[1037,6191,6194],{"className":6192,"code":6193,"language":1042},[1040],"修改后的 ARMv8 memory model\nRISC-V RVWMO\n",[1001,6195,6193],{"__ignoreMap":1045},[1016,6197],{},[1019,6199,6201],{"id":6200},"弱的non-multi-copy-atomic-内存模型","弱的、non-multi-copy atomic 内存模型",[981,6203,6204],{},"这种更弱。",[981,6206,6207],{},"含义是：",[1037,6209,6212],{"className":6210,"code":6211,"language":1042},[1040],"不同处理器可能以不同顺序看到另一个处理器的写操作。\n",[1001,6213,6211],{"__ignoreMap":1045},[981,6215,6216],{},"这会让程序推理非常困难。",[981,6218,6189],{},[1037,6220,6223],{"className":6221,"code":6222,"language":1042},[1040],"ARMv7\n原始 ARMv8\nIBM POWER\nDEC Alpha\n",[1001,6224,6222],{"__ignoreMap":1045},[981,6226,6227],{},"课件最后也指出，最近的共识认为这种模型可能太弱了。",[1016,6229],{},[985,6231,6233],{"id":6232},"第-90-页release-consistency释放一致性","第 90 页：Release Consistency，释放一致性",[981,6235,6236],{},[3227,6237],{"alt":3227,"src":6238},"\u002Fimg\u002FComputerOrganization\u002FL12-CacheCoherence-29.png",[981,6240,6241,6242],{},"这一页讲一种更实用的弱一致性思想：",[1012,6243,6244],{},"不要要求所有普通内存访问都严格有序，只在同步点保证顺序。",[981,6246,3678],{},[1037,6248,6251],{"className":6249,"code":6250,"language":1042},[1040],"Acquire\nCritical\nRelease\nOther Code\n",[1001,6252,6250],{"__ignoreMap":1045},[981,6254,6255],{},"对应锁的逻辑：",[1037,6257,6260],{"className":6258,"code":6259,"language":1497,"meta":1045},[1495],"lock();      \u002F\u002F Acquire\n临界区;      \u002F\u002F Critical section\nunlock();    \u002F\u002F Release\n",[1001,6261,6259],{"__ignoreMap":1045},[1016,6263],{},[1019,6265,6267],{"id":6266},"acquire-是什么","Acquire 是什么？",[981,6269,6270],{},"Acquire 是“获取锁”或“获得共享数据访问权”。",[981,6272,6273],{},"它要求：",[1037,6275,6278],{"className":6276,"code":6277,"language":1042},[1040],"Acquire 之后的临界区读写，不能被提前到 Acquire 之前。\n",[1001,6279,6277],{"__ignoreMap":1045},[981,6281,6282],{},"直觉是：",[1037,6284,6287],{"className":6285,"code":6286,"language":1042},[1040],"你必须先拿到锁，才能读写临界区里的共享数据。\n",[1001,6288,6286],{"__ignoreMap":1045},[981,6290,6291],{},"如果临界区里的读取被提前到拿锁之前，就可能读到别人还没发布完成的数据。",[1016,6293],{},[1019,6295,6297],{"id":6296},"release-是什么","Release 是什么？",[981,6299,6300],{},"Release 是“释放锁”或“发布更新”。",[981,6302,6273],{},[1037,6304,6307],{"className":6305,"code":6306,"language":1042},[1040],"临界区里的写操作，必须在 Release 对其他处理器可见之前完成。\n",[1001,6308,6306],{"__ignoreMap":1045},[981,6310,6282],{},[1037,6312,6315],{"className":6313,"code":6314,"language":1042},[1040],"你必须先把临界区里的更新做好，再告诉别人“我释放锁了”。\n",[1001,6316,6314],{"__ignoreMap":1045},[981,6318,6319],{},"否则别人拿到锁之后，可能看不到你刚刚在临界区做的修改。",[1016,6321],{},[1019,6323,6325],{"id":6324},"图中的-p1-和-p2-怎么理解","图中的 P1 和 P2 怎么理解？",[981,6327,6328],{},"P1 先进入临界区：",[1037,6330,6333],{"className":6331,"code":6332,"language":1042},[1040],"P1 Acquire\nP1 Critical：修改共享数据\nP1 Release\n",[1001,6334,6332],{"__ignoreMap":1045},[981,6336,6337],{},"P2 后进入临界区：",[1037,6339,6342],{"className":6340,"code":6341,"language":1042},[1040],"P2 Acquire\nP2 Critical：读取共享数据\nP2 Release\n",[1001,6343,6341],{"__ignoreMap":1045},[981,6345,6346],{},"Release Consistency 保证：",[1037,6348,6351],{"className":6349,"code":6350,"language":1042},[1040],"P1 在 Critical 中的更新，\n必须在 P1 的 Release 之前对外可见；\n\nP2 的 Critical 读取，\n必须发生在 P2 的 Acquire 之后。\n",[1001,6352,6350],{"__ignoreMap":1045},[981,6354,6355],{},"所以 P2 acquire 成功后，应该能看到 P1 release 之前发布的更新。",[981,6357,6358],{},"课件第 90 页总结得很清楚：consistency 只在进程通信数据时才重要；一个进程向其他进程共享更新时需要 consistent view，其他进程在获得共享数据访问权后需要接收更新。",[1016,6360],{},[985,6362,6363],{"id":6363},"总结这几页",[981,6365,6366],{},"这几页的逻辑是：",[1037,6368,6371],{"className":6369,"code":6370,"language":1042},[1040],"第 85 页：\nStore buffer 提高性能，但让自己的写先被自己看到，别人稍后看到。\n\n第 86 页：\nTSO 允许两个处理器都读到旧值 0，这是 SC 不允许的。\n\n第 87 页：\n强模型更好理解但难实现高性能；弱模型更快但需要 fence。\n\n第 88 页：\n生产者-消费者需要 fence，保证 data 和 flag 的访问顺序。\n\n第 89 页：\n内存模型从强到弱可以分为 SC、TSO、弱 MCA、弱 non-MCA。\n\n第 90 页：\nRelease consistency 只在 acquire\u002Frelease 这类同步点保证必要顺序。\n",[1001,6372,6370],{"__ignoreMap":1045},[981,6374,6375],{},"最关键的一句话是：",[978,6377,6378],{},[981,6379,6380],{},[1012,6381,6382],{},"Store buffer 让处理器更快，但会打破“所有人立刻按程序顺序看到写入”的直觉；所以现代处理器需要 memory consistency model 和 fence\u002Facquire\u002Frelease 来规定什么时候必须保持顺序。",{"title":1045,"searchDepth":6384,"depth":6384,"links":6385},4,[6386,6388,6392,6405,6412,6434,6451,6458,6462,6466,6467,6472,6473,6474,6479,6483,6488,6493,6529,6530,6531,6535,6549,6555,6560],{"id":987,"depth":6387,"text":988},2,{"id":993,"depth":6387,"text":994,"children":6389},[6390],{"id":1021,"depth":6391,"text":1022},3,{"id":1059,"depth":6387,"text":1060,"children":6393},[6394,6395,6396,6400,6404],{"id":1063,"depth":6391,"text":1064},{"id":1327,"depth":6391,"text":1328},{"id":1407,"depth":6391,"text":1408,"children":6397},[6398,6399],{"id":1412,"depth":6384,"text":1413},{"id":1450,"depth":6384,"text":1451},{"id":1483,"depth":6391,"text":1484,"children":6401},[6402,6403],{"id":1487,"depth":6384,"text":1488},{"id":1532,"depth":6384,"text":1533},{"id":1629,"depth":6391,"text":1630},{"id":1655,"depth":6387,"text":1656,"children":6406},[6407,6408,6409,6410,6411],{"id":1659,"depth":6391,"text":1660},{"id":1698,"depth":6391,"text":1699},{"id":1741,"depth":6391,"text":1742},{"id":1793,"depth":6391,"text":1794},{"id":1825,"depth":6391,"text":1826},{"id":1876,"depth":6387,"text":1877,"children":6413},[6414,6415,6419,6423,6424,6427,6428,6432,6433],{"id":1880,"depth":6391,"text":1881},{"id":1907,"depth":6391,"text":1908,"children":6416},[6417,6418],{"id":1911,"depth":6384,"text":1912},{"id":1937,"depth":6384,"text":1938},{"id":1974,"depth":6391,"text":1975,"children":6420},[6421,6422],{"id":1981,"depth":6384,"text":1982},{"id":1994,"depth":6384,"text":1995},{"id":2016,"depth":6391,"text":2017},{"id":2154,"depth":6391,"text":2155,"children":6425},[6426],{"id":2176,"depth":6384,"text":2177},{"id":2309,"depth":6391,"text":2310},{"id":2344,"depth":6391,"text":2345,"children":6429},[6430,6431],{"id":2357,"depth":6384,"text":2358},{"id":2382,"depth":6384,"text":2383},{"id":2396,"depth":6391,"text":2397},{"id":2417,"depth":6391,"text":2418},{"id":2473,"depth":6387,"text":2474,"children":6435},[6436,6437,6438,6439,6440,6441,6442,6443,6444,6445],{"id":2477,"depth":6391,"text":2478},{"id":2516,"depth":6391,"text":2517},{"id":2554,"depth":6391,"text":2555},{"id":2590,"depth":6391,"text":2591},{"id":2662,"depth":6391,"text":2663},{"id":2748,"depth":6391,"text":2749},{"id":2837,"depth":6391,"text":2838},{"id":2867,"depth":6391,"text":2868},{"id":2903,"depth":6391,"text":2904},{"id":2953,"depth":6391,"text":2954,"children":6446},[6447,6448,6449,6450],{"id":2957,"depth":6384,"text":2958},{"id":2978,"depth":6384,"text":2979},{"id":3001,"depth":6384,"text":3002},{"id":3024,"depth":6384,"text":3025},{"id":3055,"depth":6387,"text":3056,"children":6452},[6453,6454,6455,6456,6457],{"id":3062,"depth":6391,"text":3063},{"id":3098,"depth":6391,"text":3098},{"id":3124,"depth":6391,"text":3125},{"id":3158,"depth":6391,"text":3159},{"id":3182,"depth":6391,"text":3183},{"id":3216,"depth":6387,"text":3217,"children":6459},[6460,6461],{"id":3234,"depth":6391,"text":3235},{"id":3280,"depth":6391,"text":3281},{"id":3340,"depth":6387,"text":3341,"children":6463},[6464,6465],{"id":3359,"depth":6391,"text":3360},{"id":3398,"depth":6391,"text":3399},{"id":3462,"depth":6387,"text":3463},{"id":3501,"depth":6387,"text":3502,"children":6468},[6469,6470,6471],{"id":3516,"depth":6391,"text":3517},{"id":3534,"depth":6391,"text":3534},{"id":3562,"depth":6391,"text":3563},{"id":3588,"depth":6387,"text":3589},{"id":3663,"depth":6387,"text":3664},{"id":3729,"depth":6387,"text":3730,"children":6475},[6476,6477,6478],{"id":3741,"depth":6391,"text":3742},{"id":3759,"depth":6391,"text":3760},{"id":3795,"depth":6391,"text":3795},{"id":3834,"depth":6387,"text":3835,"children":6480},[6481,6482],{"id":3846,"depth":6391,"text":3847},{"id":3887,"depth":6391,"text":3888},{"id":3919,"depth":6387,"text":3920,"children":6484},[6485,6486,6487],{"id":3926,"depth":6391,"text":3927},{"id":3972,"depth":6391,"text":3973},{"id":4004,"depth":6391,"text":4005},{"id":4029,"depth":6387,"text":4030,"children":6489},[6490,6491,6492],{"id":4036,"depth":6391,"text":4037},{"id":4065,"depth":6391,"text":4066},{"id":4088,"depth":6391,"text":4089},{"id":4126,"depth":6387,"text":4127,"children":6494},[6495,6496,6497,6505,6506,6507,6508,6509,6510,6511,6512,6513,6517,6518,6522,6523,6527,6528],{"id":4148,"depth":6384,"text":4149},{"id":4186,"depth":6384,"text":4187},{"id":4230,"depth":6391,"text":4231,"children":6498},[6499],{"id":4282,"depth":6384,"text":4282,"children":6500},[6501,6503,6504],{"id":4286,"depth":6502,"text":4287},5,{"id":4326,"depth":6502,"text":4327},{"id":4355,"depth":6502,"text":4356},{"id":4379,"depth":6391,"text":4380},{"id":4435,"depth":6391,"text":4436},{"id":4470,"depth":6391,"text":4471},{"id":4560,"depth":6391,"text":4561},{"id":4640,"depth":6391,"text":4641},{"id":4651,"depth":6391,"text":4652},{"id":4697,"depth":6391,"text":4698},{"id":4750,"depth":6391,"text":4751},{"id":4802,"depth":6391,"text":4803,"children":6514},[6515,6516],{"id":4817,"depth":6384,"text":4818},{"id":4851,"depth":6384,"text":4852},{"id":4876,"depth":6391,"text":4877},{"id":4947,"depth":6391,"text":4948,"children":6519},[6520,6521],{"id":4965,"depth":6384,"text":4966},{"id":4989,"depth":6384,"text":4990},{"id":5028,"depth":6391,"text":5029},{"id":5110,"depth":6391,"text":5111,"children":6524},[6525,6526],{"id":5133,"depth":6384,"text":5133},{"id":5150,"depth":6384,"text":5150},{"id":5192,"depth":6391,"text":5193},{"id":5254,"depth":6391,"text":5255},{"id":5370,"depth":6387,"text":5371},{"id":5453,"depth":6387,"text":5454},{"id":5616,"depth":6387,"text":5617,"children":6532},[6533,6534],{"id":5628,"depth":6391,"text":5629},{"id":5676,"depth":6391,"text":5677},{"id":5719,"depth":6387,"text":5720,"children":6536},[6537,6541,6542,6543,6544,6545,6547],{"id":5730,"depth":6391,"text":5731,"children":6538},[6539,6540],{"id":5754,"depth":6384,"text":5755},{"id":5827,"depth":6384,"text":5828},{"id":5847,"depth":6391,"text":5848},{"id":5900,"depth":6391,"text":5901},{"id":5945,"depth":6391,"text":5946},{"id":5971,"depth":6391,"text":5971},{"id":6012,"depth":6391,"text":6546},"生产者端：fence w,w",{"id":6049,"depth":6391,"text":6548},"消费者端：fence r,r",{"id":6098,"depth":6387,"text":6099,"children":6550},[6551,6552,6553,6554],{"id":6110,"depth":6391,"text":6111},{"id":6128,"depth":6391,"text":6129},{"id":6173,"depth":6391,"text":6174},{"id":6200,"depth":6391,"text":6201},{"id":6232,"depth":6387,"text":6233,"children":6556},[6557,6558,6559],{"id":6266,"depth":6391,"text":6267},{"id":6296,"depth":6391,"text":6297},{"id":6324,"depth":6391,"text":6325},{"id":6363,"depth":6387,"text":6363},[903],"多处理器共享内存背景、snoopy\u002Fdirectory 一致性协议、memory consistency 与 fence 指令笔记","md",null,{"slots":6566},{},{"text":810,"minutes":811,"time":812,"words":813},{"title":808,"description":6562},{"loc":807,"images":6570},[6571,6572,6573,6574,6575,6576,6577,6578,6579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,6595,6596,6597,6598,6599],{"loc":3229},{"loc":3507},{"loc":3594},{"loc":3669},{"loc":3735},{"loc":3840},{"loc":4132},{"loc":4236},{"loc":4385},{"loc":4441},{"loc":4476},{"loc":4566},{"loc":4646},{"loc":4657},{"loc":4703},{"loc":4756},{"loc":4808},{"loc":4882},{"loc":4953},{"loc":5034},{"loc":5116},{"loc":5198},{"loc":5260},{"loc":5376},{"loc":5459},{"loc":5622},{"loc":5725},{"loc":6104},{"loc":6238},[6601,6602],"计算机组成原理","课程笔记","tech","LMPfUEI63W1SaLnYQlcJ6khXuczKIafN2kUnNL5wfe8",[6606,6607],{"title":799,"path":798,"stem":797,"date":653,"type":6603,"children":-1},{"title":817,"path":816,"stem":815,"date":653,"type":6603,"children":-1},1789057282645]