Daily Rust 有关所有权和生命周期的一些问题 首先看一段代码 use std::rc::Rc; #[derive(Debug)] struct Node { id: usize, downstream: Option<Rc<Node>>, } impl Node { pub fn new(id: usize) -> Self { Self { id, downstream: None, } } pub fn update_downstream(&mut self, do…
Daily Rust 有关所有权和生命周期的一些问题 首先看一段代码 use std::rc::Rc; #[derive(Debug)] struct Node { id: usize, downstream: Option<Rc<Node>>, } impl Node { pub fn new(id: usize) -> Self { Self { id, downstream: None, } } pub fn update_downstream(&mut self, do…
Lecture 16 run一个thread都涉及到了什么 比较常规的知识点,选择一个execution context,设置状态(pc, stack等),然后开始执行 对于同一个core上的multithread来说,os并不负责 os只负责粗粒度的调度,保证每个进程都能分享硬件资源 但是在硬件中利用多线程隐藏访存延迟的角度来说,用os调度代价太高了。所以在一个核上的若干个execution context,是由硬件来调度的 比如数据库中的latch,利用自旋锁实现就更好一些。因为这些都是轻量级的短时锁,不会等待…
Lecture 13 cache之间用队列,可能当队列满的时候导致死锁 因为一个队列中的request会需要在另一个队列中进行response,也就是一个队列中的work的完成需要另一个队列的resource 当队列满的时候,两个queue都需要对方queue的resource,导致了死锁 一个解决办法是可以扩大queue的容量,到系统最大事务数量 第二种方法是消除依赖 一个队列依赖另一个队列的空间,实际上是一个队列中的request依赖另一个队列的response 所以我们将request和response拆开,…
通过链表理解Rust中的Ownership 我们通过leetcode中的一道链表题来理解rust中的链表 #[derive(PartialEq, Eq, Clone, Debug)] pub struct ListNode { pub val: i32, pub next: Option<Box<ListNode>> } leetcode中rust的链表定义是这样的 可以看到,我们有clone的属性,但没有copy的属性,也就是说我们在赋值的时候的语义是移动,而非复制 而根据结构体的定义来看…
Lecture 10 一个小复习,执行一个写操作在cache层面会发生什么 我们要考虑该地址不在cache中,以及cache满时要evicit一个cache line,并且如果该cache line是dirty的,我们还需要将该cache line写回 单核系统上也会有cache coherence问题 发生在CPU和其他设备通讯的过程中 这也就是为什么有的设备IO空间是不可缓存的 或者需要让操作系统显式的flush这些page,或者这些cache line 所谓的sufficiently separated ti…
Lecture 7 异步的send和recv,我们需要返回一个handle来检查数据是否已经被正确的发送/接收了,这样我们才能安全的继续操作数据 即便我们用了pipelined的方法来传递消息,只要缓冲区不是无限大的,我们还是会得到一个没有流水化的执行过程 计算强度,computation / commnunication,越高越好 说明算法的限制在计算,而非通讯 inherent communication,取决于我们的算法,通过优化算法来优化通讯成本 artifactual communication,取决于算…
Lecture 4 截图比较诡异 这里老师问的是这段代码里那个for loop是parallel的 答案是没有,这整个函数都是按顺序执行的,真正的并发,或者说叫逻辑上的并发发生在调用函数的时候 这里是SPMD模型,相同的程序对应的是不同的数据。在abstraction层级,我们认为在调用函数的时候,ISPC会生成若干个program instance,每个instance有自己的progranIndex,他们都执行这段代码,只不过是每个instance负责不同的数据。 要注意的是这里是abstraction,ISP…
对2PL的一些补充 主要的资料来自于wiki 2PL有两个经典的变体,分别是S2PL(strict-2PL)和SS2PL(strong strict-2PL or rigorous-2PL) 我们通过这张图来理解2PL以及其他相关的一些并发控制手段 S2PL即所有的写锁在事务提交的时候才能释放 SS2PL则是对于所有的锁,都只能在事务提交的时候才能释放 S2PL可以保证不会脏读,因为任何处于活跃事务中的数据项都会处于写锁中。所以只要我们通过读锁来保证我们读到的数据项没有被写锁占有,那么这个数据项就是一致的,即不会脏…
这里就是记录一下我在听课过程中感觉比较重要或者比较难懂的知识点,较为零散 Lecture 1 摩尔定律还在生效,但是提高能效的方式正在变化 这个是具体解释,在未来,我们可能不会同时用到所有的晶体管 同时,指令级并行不能一直加速,因为一个程序中不太可能出现若干条不相关的指令 功耗墙 提高主频也会提高功耗,同时散热也是主要的问题 Lecture 2 这里的指令流一致性,指的是多个数据执行的指令流是相同的 比如一个SIMD指令中的若干个数据都有相同的指令流(相同的分支),那么我们就可以跳过不必要的分支来加速执行 反过来,…
记录一些我认为并不常见但是比较有用或者比较有趣的知识点 广义的系统内存空间包括IO空间和内存空间,不同指令集对系统内存空间的定义各不相同。X86指令集包含独立的IO空间和内存空间,对这两部分空间的访问需要使用不同的指令:内存空间使用一般的访存指令,IO空间使用专门的in/out指令。而MIPS、ARM、LoongArch等RISC指令集则通常不区分IO空间和内存空间,把它们都映射到同一个系统内存空间进行访问,使用相同的load/store指令。处理器对IO空间的访问不能经过Cache,因此在使用相同的load/st…