本次比赛主要考察项目设计,通过使用英伟达相关硬件来构建出自己的一个框架。我们DDST实验室小组计划通过NV的GPU/DPU/RDMA构建一个分布式的大模型训推框架。
由于只有两天时间,肯定不是从零开始,所以相当于基于FlexGen的开源代码进行改编;毕竟是设计类比赛,拿奖玄学,看吹逼能力和运气。由于赛前有两位硕博因故未能出席,因此只能由研究DOCA的博士生来带我们两个本科生。我之前从来没有接触过DOCA,所以相当于速通自学,但其实也不难,就是配环境比较恶心。
具体工作我的任务是为write_tensor和read_tensor两个函数增加编码和解码过程,让他们在DPU处执行编码和解码,然后发送到RDMA,让RDMA远程传输这些张量的时候能够降低带宽的使用,从而缓解RDMA网络带宽逊于本地访存的性能瓶颈。
在gcc/g++编译器中,只有安装在默认搜索路径usr/include这类路径对第三方库的引用能够使用#include <doca_error.h>这种形式,其余的库函数是不行的;很遗憾,我要使用的函数并满足上述条件,因此采用比较挫的方法,就是 ...
Self-Introduction:
Hello, I’m Weiquan Huang, a third-year Software Engineering student at Shanghai Jiao Tong University. I’m more familar with C++ as my programming language, and I’ve built a strong foundation in computer systems through courses like Distributed Systems and Operating Systems. My key projects include developing the LSMKV Log-Structured Merge Tree, and the ChFS Distributed File System. I also participated in my university’s research program, designing an RDMA-based Adaptive Radix ...
协程与线程辨析
协程与线程的区别:
协程只在用户态进行切换,协程上下文切换开销比较小(仅寄存器和栈),协程栈大小灵活且通常来说比较小,一个线程有多个协程,同一时间内一个线程仅执行一个协程,协程在C++通过主动让出来调度
线程切换需要进入内核态,调度由操作系统控制,如果同CPU切换了属于不同进程的线程会导致上下文切换开销大(如PCB/VMA/CR3等),线程栈固定且通常大很多,线程是CPU调度的最小单元,CPU同一个时间内只执行一个线程(创建线程数的上限和虚拟内存空间有关!!!)
协程的栈比线程的栈小
好处:在有限内存内能够创建更多协程,支持更多的并发
坏处:运行在协程上的程序,函数调用不能太深,不然会爆栈
如何解决爆栈问题
有栈协程可以手动设置栈的大小,或者部分语言可以设置动态扩容的栈
无栈协程通过将协程内语句抽象为有限状态机,将各个状态离散地存在堆上来避免爆栈,不过这就比较费时间
协程通常用在I/O密集型的任务,比如DART一个设计就是,scan操作会同时对多个slot发出获取该slot指向的远端数据节点的RDMA read请求,当一个 ...
场景:测远端RDMA读SSD的带宽,使用InfiniBand网卡
RDMA prepareRDMA在CPU-DRAM层面的连接是比较常规的,但是对于新手来说容易忽略一些事情,而且这种代码比较繁琐,也没什么所谓的逻辑性,通常是哪里细节之类的没处理好导致寄了
在RDMA连接之前,需要先TCP连接,交换彼此的GID/LID/QP等一众元数据,而且是需要双方都互相交换的
交换完元数据之后,两侧的RDMA程序都需要将自己的状态转为RTS(Ready to Send),顺序一般是INIT->RTR->RTS
1234567891011121314read(tcp_fd, &meta, sizeof(meta)); // meta is metadata.write(tcp_fd, &client_meta, sizeof(client_meta));...memset(&attr, 0, sizeof(attr)); attr.qp_state = IBV_QPS_RTS; attr.sq_psn = 0; attr.timeout ...
计算机系统
未读2-23 con本节介绍了一些让web服务器能够并发的方法
1,创建进程这里我们看代码,在父进程accept到请求后,子进程关闭监听fd,父进程关闭连接fd,这样子可以避免内存泄漏
1234567891011121314151617181920int main(int argc, char **argv){ int listenfd, connfd; struct sockaddr_in clientaddr; socklen_t clientlen = sizeof(clientaddr); Signal(SIGCHLD, sigchld_handler); listenfd = Open_listenfd(argv[1]); while (1) { connfd = Accept(listenfd, (SA *) &clientaddr, &clientlen); if (Fork() == 0) { Close(listenfd); /* Child closes its l ...
计算机系统
未读不得不吐槽你软的计算机网络教育真的十分零散,建议从计算机系引入计网,并且删除《无人系统设计》捏
2-20 net这只是入个门
局域网有一个hub/switch,被称为交换机,可以将与其相连的机器进行局部通信;通信的时候是需要标识的,这里在内部是使用Mac来标识地址的
局域网之间可以通过bridge来进行通信
上面的统称为局域网,LAN,因为他们的范围有限;不同的局域网之间可以通过路由器来链接,路由器之间的连接为WAN广域网
如果要从某个主机将数据传给另一个主机,那么网络上是有一些机制的,比如子网掩码可以获取到目标主机和发送主机是否在同一个局域网这个信息(IP地址和子网掩码255.255.255.0取与);网关是局域网和外部网络通信的接口,连接网络的节点:IP地址?IPv4是32位4字节的地址(其实是按照整型数来存储的),不能作为主机的唯一标识,一般是分层的(类似于你可能在校内网被分配了一个地址,但是校内网在整个世界对外的地址是另一个地址),通常用点十进制方式来表示,以下是一些常用的IP地址:
127.0.0.1 localhost主机的回送地址loopback addres ...
前排声明:本系列笔记为ICS2课堂笔记,由于本人在大二下才开始电子化笔记,因此只能上传ICS2的笔记,故本节有缺失
鲁棒IO主要是为了实现IO读取的高效性和鲁棒性,高效性主要是通过缓存buffer来实现的,buffer会读取文件里面的一段内容,然后根据实际的读取需要来进行读取,如下图
实际上的I/O是基于底层IO来实现的,无论是standard还是rio,比如之前常说的文件流stream其实也是一个类buffer的东西,会根据一些条件,比如\n fflush(stdout)来对缓冲区的东西进行真正的写入
RIO的代码还是有意思的,可以看看:
short count实际读取的数据小于要求的数据:
实际的数据量并没有要求的那么多
确实没读好
计算机系统
未读2-17 mallocmalloc函数概览,要求多少空间就开多少能用的空间,不过事实上是有一定的多余空间的——必须开的是地址8对齐的空间,因为type *p=(type *)malloc(sizeof(type)),在实际使用的时候,为了保险起见,能够让空间能够存放uint64_t类型的数据,所以强制8对齐地址,这会导致一定的空间浪费
拓展堆区空间的函数sbrk(int),如果开空间成功,返回原来的栈顶(堆区空间的可伸长的末尾),参数可以为负,表示收缩空间
优化堆区空间内存的性能:
throughput是指存取数据的速度,比如1秒能够存/取多少数据
utilization是指空间利用率
碎片:内部碎片与外部碎片内部碎片是指给数据开空间的时候,为了让数据满足地址8对齐,或者为了加上内存数据块隐形链表指针,导致的已使用但是并非用于存储数据的空间;外部碎片是指,在内部总空间足够,但是没有一块连续的能够存储预开空间大小的空间,就会产生外部碎片
堆区内存块的结构、只读数据区域、数据区域(可读写);乃至于局部变量和全局变量也是在不同的区域(局部变量更有可能直接在寄存器里面)
链接一下看看!这里数据和代码(指令)区隔得比较远,可以看到%rip需要再加上较多的偏移量才可以到达数据区;这里其实相当于将两个文件的指令整合在一起,将两个文件的数据整合在一起,数据和指令倒还是分开的
可执行可链接模式文件 ...
计算机系统
未读2-11 ramSRAM在访问速度、传送数据量、信息存储持久度、以及信息抗干扰(主要体现为干扰后能恢复原来的状态)优于DRAM,但是太贵了内存控制器会将行列信息分布传送到DRAM内,这样子对于addr的引线就只需要两条(0-3就是00-11,如果是一维数组直接输入下标,则需要0-15即0000-1111,引线的条数就是bit数);一个超单元其实涵盖了8个bit;这里就是先传一个row,DRAM将对应行的信息传到行缓冲区,然后传col,DRAM将缓冲区中列的内容传给data引线(共8条)这里一个内存模块(memory module)有8个DRAM芯片,每个超单元存一个字节,一次可以取8字节
总线(bus) 是携带地址、数据、控制信号的并行管道的集合,通常总线被许多设备共用;读事务从主存传送数据到CPU,写事务从CPU传送数据到主存考虑一个movq A, %rax,分为三个步骤:1,CPU的总线接口将需要的地址传给主存2,主存将对应地址的内容传给总线接口3,总线接口数据传给寄存器如果是movq %rax, A,则是先总线接口去找主存对应地址,然后将寄存器内容写入总线接口,然后数据从总线接口 ...