LLM高性能计算/通信需要的知识
文章平均质量分 87
会逐渐更新CUDA编程、C++知识、MPI/NCCL通信、性能优化(通信/计算)的知识,其实是实习期间的笔记。
小马敲马
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
[4.2-1] NCCL新版本的register如何实现的?
本文介绍了NCCL中实现GPU间零拷贝数据传输的机制。主要分为机内和机间两种情况:机间通过ncclRegisterP2pNetBuffer注册网络缓冲区,机内通过ncclRegisterP2pIpcBuffer注册IPC缓冲区。关键步骤包括判断传输方向、注册缓冲区、生成设备工作结构ncclDevWorkP2p以及为非自发送创建代理操作。特别说明了在单进程和多进程场景下的不同处理方式,单进程只需一个代理操作,而跨进程传输需要两个代理操作(send和recv)。通过这种注册机制,NCCL实现了高效的数据传输路径原创 2025-08-11 18:07:31 · 1155 阅读 · 0 评论 -
[4.2-2] NCCL新版本的register如何实现的?
本文分析了NCCL中跨进程P2P通信内存注册的实现过程。首先通过ncclRegisterP2pIpcBuffer进行IPC缓冲区的注册,根据环境变量选择本地注册或图形注册方式。核心函数ipcRegisterBuffer实现了跨进程内存映射,使本地进程能直接访问对端内存。注册过程包括:检查是否已注册、获取缓冲区信息、建立代理连接、创建IPC句柄等步骤。通过复用已注册信息可优化性能。该机制实现了高效的进程间直接内存访问,为NCCL的P2P通信提供了基础支持。原创 2025-08-11 17:57:06 · 915 阅读 · 0 评论 -
[4.1] NCCL如何编排alltoall的多个send recv任务?
NCCL Group通信机制分析 NCCL的AlltoAll操作通过Group机制实现,将多个Send/Recv操作批量执行。核心流程包括: GroupStart:仅增加ncclGroupDepth计数器,标记进入组操作模式 任务收集:每个Send/Recv操作通过ncclEnqueueCheck将任务参数打包为ncclInfo结构,存入ncclAsyncJobs队列 GroupEnd:当最外层GroupEnd时: 检查Group深度合法性 打包所有任务到ncclGroupJobMain结构 根据阻塞/非阻原创 2025-08-11 17:52:20 · 1221 阅读 · 0 评论 -
[1.1节] PMPP chapter 1-3 notes
本文介绍了CUDA编程模型的基本概念和核心思想。主要内容包括:1) CUDA通过CPU/GPU异构计算充分发挥并行能力;2) GPU计算的历史发展背景;3) CUDA程序结构,包含host和device代码,以及kernel函数的定义;4) 矩阵乘法示例展示数据并行性实现;5) 设备内存管理及数据传输机制;6) 线程组织模型与kernel调用方式。CUDA通过扩展C语言语法支持异构编程,利用多级线程层次结构实现高效并行计算,其中kernel函数生成大量轻量级线程执行数据并行任务。原创 2025-07-21 13:00:00 · 1088 阅读 · 0 评论 -
[3.5] 高级集体通讯 理论+代码
摘要:本文介绍了MPI中的两种规约操作MPI_Reduce和MPI_Allreduce。MPI_Reduce将各进程的输入数组按指定操作(如求和、最大值等)规约后返回给根进程,函数原型包含发送/接收缓冲区、数据类型和操作类型等参数。MPI_Allreduce则扩展为所有进程都能获取规约结果,相当于先执行Reduce再广播。文中提供了两个完整的代码示例,分别演示如何使用这两个函数计算随机数组的局部和与全局平均值。通过mpirun运行测试显示,4个进程各处理100个元素时,Allreduce版本让所有进程都能访原创 2025-06-13 19:00:00 · 463 阅读 · 0 评论 -
[3.4] 集合通信 理论+代码
一个广播发生的时候,一个进程会把同样一份数据传递给一个 communicator 里的所有其他进程。根节点把数据传递给所有其他的节点,其他的节点接收根节点的数据。只是使用了进程0的一次次的传递数据。假设水平的轴代表的是程序的执行,小圆圈代表不同的进程。首先生成一个随机数的数组,scatter给不同进程,每个进程的到相同多数量的随机数,每个进程计算各自的avg,然后最后求总的avg。它会会设计一个指定的根进程,根进程会将数据发送到 communicator 里面的所有进程,但是给每个进程发送的是。原创 2025-06-13 01:32:37 · 1014 阅读 · 0 评论 -
[3.3] 阻塞与非阻塞通信 理论+代码
012每个域有五个单元,最后一个域有6个单元。完成消息的接收(数据已经被复制到接收缓冲区中)。此时,直到完成发送和接收,这两个函数会让进程在此处“停住”。假设游走器只能采取整数大小的步长,我们可以轻松地将域在每个进程中划分为大小近乎相等的块。并将域的大小定义为Max - Min + 1,(因为游走器包含。问题描述:给定左右边界Min,Max和游走器Walker。发送和接收操作被立即返回,通信操作在后台继续进行。为 20,并且我们有四个进程,则将像这样拆分域。完成消息的发送(或在缓冲区中完成存储)和。原创 2025-04-05 14:51:52 · 453 阅读 · 0 评论 -
[3.2] 深入了解recv参数列表里的status
例如,控制端/执行子程序在交换变量大小的消息时通常会大量使用。函数,则操作完成后将在该结构体中填充有关接收操作的其他信息。下一节将通过完整的代码例子说明send和recv为什么是阻塞通信。对象,则可以通过state.MPI_SOURCE访问rank。消息的长度,它在在结构体中没有预定义的元素。在实际接收消息之前查询消息大小。会阻塞具有匹配标签和发送端的消息。发送端的rank,发送端的rank存储在结构体。在库文件中的定义如下,可以看到与。结构体的地址作为参数,可以使用。消息的标签,同上访问方式,访问。原创 2025-04-05 14:17:46 · 953 阅读 · 0 评论 -
[3.1] MPI的基础结构 & send / recv 机制
消息传递模型?它其实只是指程序通过在进程间传递消息(消息可以理解成带有一些信息和数据的一个数据结构)来完成某些任务。MPI在消息传递模型设计上的经典概念:通讯器(communicator):一组能够互相发消息的进程。在这组进程中,每个进程会被分配一个序号,称作秩(rank),进程间显性地通过指定秩来进行通信。点对点(point-to-point)通信:不同进程间发送和接收操作。一个进程可以通过指定另一个进程的秩以及一个独一无二的消息标签tag)来发送消息给另一个进程。原创 2025-03-30 18:28:35 · 943 阅读 · 0 评论 -
[3.0] MPI原理+代码实战
笔者目前是北京的一位Ai infra实习生(小卡拉米),上班第一天要求学会儿MPI。资料和学习记录整合成这个专栏,供自己和其他人学习和复习。本系列文章将从 MPI 的基本概念出发,逐步深入点对点通信、集体通信、高级通信操作,最终引导你掌握复杂的 group 与 communicator 管理技巧。无论你是刚接触 MPI 的新手,还是想要系统梳理知识的进阶开发者,这个系列都能为你带来清晰实用的指导。整个学习的过程我是用的C++,所以编译代码的指令是mpic++,运行可执行文件用的是mpirun。原创 2025-03-30 18:20:16 · 492 阅读 · 0 评论 -
[2.7] variant变体
std::variant是C++17引入的标准库类型,表示多个可能类型中的一个。类似于联合体(union),但是更安全易于使用。union分配的内存只管最大的成员,union的所有成员share同一个内存空间。return 0;/**/这里的int变量是未定义类型但是输出了莫名其妙的东西,所以c++17出现的variant就是为了解决这个潜在的问题。代表一个多类型的容器,容器中的值是制定类型的一种,是通用的 Sum Type,对应 Rust 的enum。是一种类型安全的union。原创 2025-03-14 17:05:01 · 946 阅读 · 0 评论 -
[2.6] C++11 原子变量 | CAS操作 | 内存顺序
c++11中提供的原子类型,内部变量通过这个原子类型管理后就变为原子变量。原子类型模板参数<T>可以指定bool、char、int、long、指针等类型(不支持浮点类型和复合类型)。原子指一系列不可被CPU上下文交换的机器指令,这些指令组合在一起就形成了原子操作。在多核CPU下,当某个CPU核心开始运行原子操作时,会先暂停其它CPU内核对内存的操作,以保证原子操作不会被其它CPU内核所干扰。由于原子操作是通过指令提供的支持,因此它的性能相比锁和消息传递会好很多。原创 2025-03-14 17:02:16 · 1121 阅读 · 0 评论 -
[2.5] 异步操作(async)--代码结合版
future是一个模板类,也就是这个类可以存储任意指定类型的数据。同时也提供了// 1 默认无参构造函数// 2 移动构造函数,转移资源的所有权// 3 使用=delete显示删除拷贝构造函数, 不允许进行对象之间的拷贝常用的一般情况下使用进行赋值操作就进行对象的拷贝,但是future对象不可用复制。如果other是右值,那么转移资源的所有权如果other是非右值,不允许进行对象之间的拷贝(该函数被显示删除禁止使用)取出future对象内部保存的数据,其中void get()原创 2025-03-06 11:29:13 · 1089 阅读 · 0 评论 -
[2.4] 右值引用 | 移动语义 | 完美转发 实现计算任务性能优化!!
是持久的、有明确内存地址的对象。原创 2025-03-06 11:25:23 · 799 阅读 · 0 评论 -
[2.3-3]weak_ptr 弱引用的智能指针
时,由于aptr是weak_ptr,它并不会增加引用计数,所以ap的引用计数仍然会是1,在离开作用域之后,ap的引用计数为减为0,A指针会被析构,析构后其内部的bptr的引用计数会被减为1,然后在离开作用域后bp引用计数又从1减为0,B对象也被析构,不会发生内存泄漏。,因为它不共享指针,不能操作资源,主要是为了通过shared_ptr获得资源的监测权,它的构造不会增加引用计数,它的析构也不会减少引用计数,纯粹只是作为一个旁观者来监视shared_ptr中管理的资源是否存在。超出作用域,它的引用计数递减到。原创 2025-03-03 20:51:55 · 717 阅读 · 0 评论 -
[2.3-2]unique_ptr独占的智能指针
unique_ptr是一个独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将 一个unique_ptr赋值给另一个unique_ptr。// 报错,不能复制但可以通过std::move来转移到其他的unique_ptr,这样它本身就不再拥有原来指针的所有权了。// 正确在c++14当中加入了,c++11中加入的是。使用new的版本重复了被创建对象的键入,但是make_unique函数则没有。());原创 2025-03-03 20:07:27 · 472 阅读 · 0 评论 -
[2.3节]什么是shared_ptr共享的智能指针?
C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理。C++11中引入了智能指针的概念,方便管理堆内存。使用普通指针,容易造成堆内存泄露(忘记释放),二次释放,程序发生异常时内存泄露等问题等,使用智能指针能更好的管理堆内存。C++里面的四个智能指针:unique_ptrshared_ptrweak_ptr其中后三个是C++11支持, 第一个已经被C++11弃用。使用这些智能指针时需要引用头文件<memory>。原创 2025-02-28 17:49:33 · 533 阅读 · 0 评论 -
[2.1节]CPU怎么实现多线程,互斥锁,条件变量?
从语义上看这里使用lock_guard会产生矛盾,但是实际上并不会出问题,因为wait提前释放锁之后会处 于等待状态,在被notify_one或者notify_all唤醒后会先获取mutex,这相当于lock_guard的mutex在 释放之后又获取到了,因此,在出了作用域之后lock_guard自动释放mutex不会有问题。解锁正在等待当前条件的线程中的一个,如果没有线程在等待,则函数不执行任何操作,如果正在等待的线程多余一个,则唤醒的线程是不确定的。同样,空了之后就不能移除元素,否则会发生下标越界。原创 2025-02-27 21:26:25 · 728 阅读 · 0 评论 -
[2.2节]lamda表达式
在C++11之后,如果Lamba表达式的函数体内有多个return语句且返回类型不一致,编译器无法自动推断的时候,此时必须显式的指定返回类型。这里使用了bool holds_alternative来判断返回的类型是什么。由于 Lambda 表达式有多个。如果希望去修改按值捕获的外部变量,那么应该如何处理呢?这就需要使用mutable选项,语句且返回类型不同,我们必须显式指定返回类型为。一般情况下,编译器会自动推断出。原创 2025-02-28 12:21:24 · 918 阅读 · 0 评论
分享