解决问题是本质
- 基本理论
- 发现问题(问题是已知和未知的矛盾,明确已知的定义和约束条件)
- 分析问题(已知与未知的关系和从已知到未知需要的条件)
- 提出假设(不要局限于具体的某个方法或途径)
- 检验假设(使用逻辑进行推演,但是实践才能证明)
- 首先要明确问题中所有涉及的概念定义
- 问题解决过程的总趋向,是先确定问题的范围,指出可能的解决方向,再逐步缩小范围,提出问题解决的一般方法和具体特殊方法,一步步进行推理以逼近问题的解决
- 问题状态—若干中间状态—目标状态,中间状态是在状态空间边缘努力逼近目标状态
- 如何使用AI解决复杂问题
- 与AI讨论确定问题边界
- 确定问题的解决流程和步骤
工作
- 应该从资源的的角度整理方法,如云计算相关等
- 如何解决问题的?
- 问题背景分解
- 业务场景选择合适的算法
- 理解算法原理
- 进行调优
- 整理输出博客
代码问题描述模板- 报错截图:包含报错文本的上下文
- 报错文本:主要是核心的报错文本
- 问题分析:
- 解决方法:
正文
- 问题的解决思维是工程师的能力
- 针对主要使用的部分进行优化
- 问题无法解决,就解决问题的假设来源
- 计算思维
- 所有算法归根结底需要用计算机语言的形式进行实现,有好的idea需要考虑在计算机描述下具有好的性能
- 离散性:计算机是用离散来模拟连续,但本质还是离散
- 存储性:可以记录过往的信息进行复用
- 循环不变量(规律) :算法的本质就是循环,找到性能好的循环不变量算法,才能充分发挥计算机的优越性
- 操作系统:将对象抽象成数据结构,再使用函数对这些数据结构进行控制和管理
- 抽象思维
- 抽象是从众多的事物中抽取出共同的、本质性的特征,最后再将该特征表达的意义赋予符号
- 人在的抽象思维是建立在感知经验思维上的一种对本质的把握
- 抽象思维的使用是人类突破物理世界束缚的本质能力(若将人的全部信息数字化,是否可以认为人在逻辑上永生)
eg:
- 计算机系统中的各种软硬件资源均可用数据结构抽象地描述其资源特性,从而忽视其实现细节
- 人体的线条其实并不明显,而雕塑是对人体的体型的特征进行抽象并使用明显的线条进行表达
- 淘宝卖商品的数量加1,其实这个1就是对商品整体数量特征的抽象
- 数字孪生概念的本质思想
- 目录思维
- 原理:
- 目录思维是基于抽象思维的对整体细节的符号化,本质是一个
键值对k:v,其中k应该是熟悉的、简略的信息 - 元素之间的关系是一对多的关系,通常形成树状结构或层次结构
- 索引结点可能产生额外的空间开销,但是有利于查询和浅拷贝
- 目录思维是基于抽象思维的对整体细节的符号化,本质是一个
- 示例
- 寄存器组的思想:使用两个寄存器操作一组寄存器,其中,Address Register:用于指定寄存器数组某一个寄存器,Data Register:用于对索引所指向的数组元素(寄存器)进行输入输出操作
- STL中deque的基本数据结构中,中央控制块和其索引多个buffer的关系
- key-value,通常配合哈希表,期望随机时间查找一个key代表的大量数据
- 原理:
- 黑盒思维(输入-规则-输出)
- 思维本质是生物的剌激反应,刺激是输入,构建的思维是规则,而能动的改造自然就是输出(改造自身也是改造自然,因为自身也是自然的一部分)
- 可以只理解输入和输出的关系,而不需要去思考规则的具体实现,节省的时间可以去搭建上层建筑(站在巨人的肩膀上才能更快的发展)
逆向思维
- 原理:放弃正向的“已有经验、方法或常识”,明确目标,然后认识问题本质,紧紧围绕“解决真正问题”的反向思考方式。
- 示例
- 从部分结果回推从而证明全局
- 汤老师劝学视频火了,那么汤老师劝不学的视频制作出来会不会火?(目标是火,如何制作视频只是一种方式)
目标思维
- 一切服务于目标,以目标为导向去思考和处理才能用最小代价获得最大收益
eg:如果将深度学习技术看作一种复杂函数的逼近算法,那么如果目标错误,即使逼近的再好,也没有好的测试正确率
- 通信控制
本思想源自操作系统中CPU对于外设的控制方式启发
1.直接方式(端口控制)
- 直接通过规范的格式告诉对方需要做什么
2.间接方式(内存映射)
- 通过某一个中间实体告诉对方,该中间实体可以存储多个对象的通信通道的索引,使用了目录思维进行简化一对多对象的控制
- 联系思维
1.定义:联系的观点是指事物内部各要素之间和事物之间相互影响、相互制约和相互作用的关系。
2.特点:
- 多样性:世界上的事物及其联系都是多样的。多角度思考加深理解
- 条件性:条件可以促进或制约事物发展,改变和创造条件不是任意的,必须尊重事物发展的客观规律。顺势而为
- 普遍性:事物内部要素、不同事物之间和整个世界的事物是普遍联系的。防微杜渐,必有联系
- 客观性:联系的存在是客观的,不以人的意志为转移。注重事实,避免主观臆断
- WWH思维
遇到问题询问自己
- 价值回归
价值定义:人类凝结在商品中无差别的劳动,以人为本
价格定义:供求双方的相互作用和博弈
- 商品的价格由价值决定,受供求关系影响;
- 商品之初供求关系影响大,商品饱和后,受供求关系影响小
商品的价格一定在其价值的平均线上下波动
- 抽象与具化
- 将一类问题的解决方法进行思考,抽象成一个数学模型,然后具化到相应问题进行快速解决。eg:动态规划的同类题目都使用dp的算法
结论+实例可以让别人更容易的理解,在向别人进行解释的时候要利用这个原则。
- 分解思维(细化粒度)
- 解决复杂问题的好方法,可以提高效率
- 将问题按照某个维度进行分解,然后思考每个部分可以利用的方法
- 编程应用:先封装底层常用的内联函数,将算法中的if和while外的算法部分均封装成独立的函数,每个函数使用assert进行准确性断言,保证每个函数的正确性,再逐层向上搭建正确的代码
eg:将问题处理对象(数据)划分的尽量小,即细粒度。细粒度通常有利于实现高并发,解决问题针对不同的模块特点使用各自对应的数据结构有利于提高效率
- 调度优化
- 细化粒度
- 定义:尽可能基于最小单位进行调度,从而使用调度较小的计算资源换取较大的的各种资源的利用率
- 示例:vllm使用动态的token级调度,而不使用静态的请求级调度,从而通过调度能够充分提高资源的利用率
- 细化粒度
- 多角度观点
同一个客观存在的事物,在不同的符号系统下会有不同的表达方式,只有熟悉这套表达方式的物体才能运行/听懂。语言是沟通不同符号系统的中间桥梁。
eg:计算机方面真正理解一个算法,是从计算机运行方面和现实抽象逻辑(人类语言)这两个方面完全的理解
- 对象(状态)+规则(方法)
- 原理:
- 对象由属性组成,这组属性的值的集合表示了对象的一个状态。
- 规则毫无差别的支配对象,这个支配是通过更改对象的属性值进行的
- 示例:
- 面向对象设计方法中的属性和方法
- 数据和算法
- 状态和外界作用
- 原理:
- 状态变化
if(条件){规则/方法:对状态的操作}// 条件的本质是对于属性的判断// 状态的本质是相关属性集// 规则对状态进行操作(改变状态或查询状态) - 负反馈策略
- 将系统的输出返回到输入端并以某种方式改变输入,进而影响系统功能的过程
- 推广到动态特征调节:对于某个特征进行监控,如果特征出现变化,则系统进行相应的变化
eg:SYN泛洪攻击的防御:一旦服务器受到攻击,SYN Half link 的数量超过系统中TCP活动Half link最大连接数的设置,系统将会认为自己受到了SYN Flood攻击,并将根据攻击的判断情况作出反应:减短SYN Timeout时间、减少SYN-ACK的重试次数、自动对缓冲区中的报文进行延时等等措施,力图将攻击危害减到最低。
- 动态规划:对于问题发展的上界与下界进行估算决定是否拓展
- 助人为乐:别人有问题而我自己恰好有能力,一定是时序上的后者(问题发生后才需要帮助)
- 负载均衡的steal进程,无等待的原子快照
- 先思后做
- 原理:通常思考的代价比较小,
示例
- 在某段时间内状态一致的验证:进行两次scan,结果相同表示一致,但可能存在ABA事件(使用时间戳进行解决)
- 两种考试类型题
- 算法类型:明确细节和计算规则,对于不同的输入可以进行运算(同一个题型改改数)
- 背诵类型:按照关键词得分
- 都需要进行不断地重复
- 降维打击
毫无干系的事情却对这个事物的发展起着决定性作用
eg:课堂上做梦即将成王,被老师打醒
- 特殊性分析
针对不同的场景进行其特点的分析
- 用魔法打败魔法
- 拟态安全防御:操作系统随着环境或时间不断变化,让攻击者无法把握规律,用不确定性防御未知的漏洞(用未知来防御未知,)
- 当业界尚未形成标准时,使用业界最认可的模型来为自己完善自己某一部分的标准。eg:人脸老化模型中如何保证面部辨识身份的不损失,使用业界最好的面部辨识模型在人脸老化过程中保证人脸的身份辨识。
- 减少系统对单一资源的依赖
并行计算机的对称多处理机系统所有计算节点共用同一总线,如果总线出现问题,将导致系统失效。
- 泛化编程GP = 数据 + 算法(两者是分离的)
- 破旧立新
linux内核的加载过程中,需要从16位实模式切换到32位保护模式,在这个过程中,不断将执行完成后的老机制代码用新机制代码覆盖,不但避免了新老机制的混用,还节省了内存
- 比率控制器
适用于速度不匹配的软硬件协同。通过中间件实现实现,通常是通过缓存慢的物质,然后输出到快的物质中。eg:高频输入的时钟,进行间隔计数而转化成低频时钟信号
- 重构
- 先使用常用的、简单的方法构造出解决问题的模型或项目代码,然后在针对模型的问题进行设计模式或功能增强
eg
- 先写出单线程程序,然后进行重构成高并发的多线程程序。
- 先写出基本的程序,然后根据所面临的问题,进行设计模式的更改
- 极简原则
- 每个类和函数都尽量保持单一职责,减少输入(形参)和输出(返回值)的复杂度
- 减少中间层的转换,每次转换意味着开销和复杂性的提高
- 有一个矛盾:模块化算不算一种增加复杂度的方法,但是减少了逻辑复杂度
- decorator修饰模式
功能 = 内核 + 修饰(等号是对右侧的封装)
- eg:计算机网络的层次结构,每一层的功能 = 下层的功能(内核)+ 本层的修饰
- 越底层越自由。
- 底层的算法应该尽量减少其约束,参数的健壮性检查不应该掺杂其他非内源性的约束。通过再次封装的修饰可以进行特化,即提高了重用性又保存了灵活性
- 计算系统的设备都保留了许多控制端口,而通过代码封装和修饰一步步抽象到应用程序,只能进行规则化的调用。
- 异构和多核
- 都是为了更好的降本增效的处理问题,但是通常会出现普适性和高性能的矛盾。如异构后降低了普适性增强了处理某类特定问题的效率,多核相反。
- 如何更好的平衡范围和性能来处理具体问题是需要思考的
- 以弱换强
- 原理:核心是
业务场景下的收益(时空开销、人机交互好···) = 付出 - 代价,牺牲不重要的部分性质,换取更需要的性质或者使需要的性质性能更好 - 注意:一旦引入了一个机制,没有用到它的利益,就会无条件背上使用它的代价。
- 示例
- 红黑树牺牲了高度平衡的特性,换取了不平衡时更少的旋转开销。
- 在基础库中使用锁,就为上层调用者引入了线程机制,减少了业务调优的余地
- 做基础框架的工程师们,请把线程看做洪水猛兽,把它留给系统工程师,别自作聪明出来找不自在,吃饱没事别它么每个接口都给我上把锁。???以后需要批判思考一下
- 原理:核心是
- 数学原理替换
- 原理:使用等效的数学公式进行逻辑运算的替换,这个替换目标是
更符合计算机的运算逻辑,提高运算效率 - 示例:
a/2等价于a>>1
- 原理:使用等效的数学公式进行逻辑运算的替换,这个替换目标是
- 控制部分+数据部分(对于数据结构的优化)
- 原理:
- 控制部分:数据部分属性的描述或者协议的规定
- 数据部分:单纯的数据值存储
- 示例:
- TCP/IP网络模型中,首部+数据组成的数据报
- 操作系统中内存分配器中,内存控制块+内存数据区块
- innoDB中表结构的compact行格式
- 原理:
- 固定大小、通过特定字符划分边界
- 计算机中数据的核心是
二进制代码,其实际的应用取决于格式转换 - 操作系统控制原理
- 建表:将数据的属性,即控制部分,抽象成一个数据结构,这个数据结构相当于一个属性表
- 位图:通过计算机中的最小单位数据单位,进行某种资源
是否使用used的区分 - 建立的表可以存放在内存中,如磁盘是一种低速设备,先将控制部分(即索引地址)加载到内存中用于增删改查,最终需要操作时,再统一操作,减少硬盘访问次数。
- 静态预编译优势
- 原理:将在运行中需要动态计算的数据,通过预先计算并存储静态数据,从而动态执行时可以极大的提高性能
- 示例
- 函数模板和类模板
- 虚幻引擎5中lumon全局光照,将动态的光线求交转换成静态的提前计算好的距离场,实时运行只需要进行查表和简单的计算
- 工程复用
- 通过已知的去近似未知的,从而降低开销
- 解决主要矛盾,为目标服务
- 计算机生成场景图片,全局光线计算量与距离呈反比,越远计算越粗放,即远处用性能差算法
- 数据结构是算法的基础
- 换一个更好的数据结构,通常比优化代码更有用
- 困难题都是通过对于已有数据结构的自定义进行的,从而通过算法提升性能
- 等价调用思想
- 只要证明两个程序的计算一致性,可以将性能差的代码替换成性能更优的代码。(编译上的等价替换)
- 通过转换统一算法运行的标准
- 进程调度CFS算法:在公平的保证上:谁亏给谁补,操作系统尽可能的让每个进程都获得同样的运行时间。在优先级的保证上:每个进程执行相同的1ms,nice值大的会执行10ms,nice值小的会执行5ms。即通过nice作为系数增加的虚拟时间,统一进程在运行时间上的调度策略到公平性上
- 局部性原理的内存化
- 局部性原理
- 时间局部性:访问过的不久还会再访问,LRU+热点优化
- 空间局部性:用过的周围可能会再用(由程序的顺序性决定),cache一致导致的连带失效
- 内存化:内存小而快,所以可以将目录和指针进行内存的常驻
- 局部性
- eg:将单链表的指针域集中到一起,放在内存中(FAT文件系统)
- 局部性原理
- 组合优势
- 将两个相同的东西通过算法虚拟出一个等于甚至超过两者之和的东西
- eg:
- RAID算法:将多个不可靠的磁盘,通过算法虚拟组合成一个又大、又快、又可靠的大磁盘
- 完成标记
- 线性的操作序列可以每隔一部分做一个完成标记,出现完成标记意味之前的部分已经完成
- 实例:
- http三次握手的seq
- 数据库中的回滚标记
- 资源的延迟分配
- 含义:申请资源时,不进行实际分配。只有使用资源时,才进行实际分配。
- 优点:
- 避免DDos攻击
- 有利于并发
- 示例:
- 写时复制COW:读内存数据时,不进行资源分配,当要写入时,分配资源的副本,最后再合并
- 懒汉单例模式:定义对象时,不进行实际的资源分配,只有调用对象自定义实例化函数才进行真正的实例化
- 三次握手的第三次握手成功,服务器才完整的分配资源,可以避免SYN泛洪攻击
- Spark:内存池+延迟分配,加快了资源分配速度,并且具有延迟分配的安全性和降低内存开销的优点
- 心跳机制
- 定义:通过周期性的信号,进行通信路径的完整性检测
- 示例:
- TCP心跳机制:当客户端和服务器长时间未进行信息交换,其中一方发送约定的特殊数据报文,等待对方回复。从而确保TCP连接的有效性
- 客户端和数据库引擎:心跳式的定期断开长连接或者客户端主动重置连接。
- 读写分离
- COW:读时共享,写时复制
- 将内存中改动的,置dirty为1,表示要写回到磁盘中
- 过程的复用
- 将数据进行尽可能的统一化,将过程函数进行复用,即将上个输入关联到下个输出。
- eg:
- shell脚本中grep的管道
- rust中的str.covert().slice().print()等等
- 相关性导致的并发问题
- 核心:相关性高的、耦合度大的代码难以实现并发和流水线执行,会降低很大的性能
- 示例:
- cpu指令流水线的障碍:指令相关——数据相关、寄存器名字相关、控制相关
- 程序并发的障碍:
- 计算机喜欢有序的东西
- 分支预测对于乱序的数据处理比较慢,因为如果猜测失误需要清空流水线,所以尽量
减少if-else的使用,增加排序的使用。
- 分支预测对于乱序的数据处理比较慢,因为如果猜测失误需要清空流水线,所以尽量
- 迭代优化
- 一个大的架构的问题解决方案,进行一个迭代优化尝试,然后对里面具体的数据结构进行一个迭代优化,虽然不能保证整体最优,但是可以保证局部最优的一个问题解决方案
- 量度策略
- 背景:很多时候并不能找到一个针对问题所有情况都具有良好性能的算法,但是通常可以找到针对问题不同情况下的最优策略。
- 原理:设置一个可以量化的转换标准,但低于该标准使用A算法处理,当高于该标准使用B算法处理(可以分成多层次)
- 示例:水的模拟在0度以下使用固态算法,在零度以上使用液态算法,在100℃以上使用气态算法
- 静态和动态
- 静态往往更加简单高效,动态往往开销大但灵活性强
- 示例
- 静态编译和动态编译,滑动窗口的静态窗口和动态窗口
- namespace的原理(待解决)
- Redis中的stream消费组模式
- cpp20
- 多核架构下的局部优化
- 每个核心都增加自己的局部缓存,以加快处理速度和解决数据一致性等相关问题
- 示例
- tcmalloc
- lapic:高级中断控制器
- 系统健壮性
- 事前预防(解决问题发生的原因),事中检测(运行中时时检测),事后解除(出现问题,抛出异常给上层解决,而不是摆烂放弃)
- 示例:
- 死锁的预防和检测以及解除,银行家算法避免进入不安全状态,检测循环等待链或者执行时间太长的进程,事后撤销资源或者kill进程
- 黄金圈模型
- 工程是解决问题导向的,每一个新技术都是在修补和平衡原有技术存在的某方面的问题,从而实现问题的解决,所以应该尽量从有原因的角度思考问题。
- 新技术的分析
- 划分:首先对新技术的内部进行划分,直到不能在划分后再使用以下部分
- 定义
What:新技术的定义应该明确其与现有技术区别的核心功能 - 作用/特点:新技术在提高效率、降低成本、增强功能等方面的用处
- 原理
Why:使用xx机制解决/提高了旧技术的问题 - 实践
How:在实际场景中的部署和应用的具体流程 - 实践中需要注意的问题:在实践过程中,难点和易错点
- 生产-缓冲-消费
- 生产者消费者模式
- 肺/鱼鳔:动脉生产氧气到肺中,静脉从肺中消费氧气
- 软件更匹配硬件
- 定义:通过平衡软件不同的特征,从而使其更加符合硬件的能力,最后提升效率
- 中庸思想:针对同一个问题的两个思路都各自有优缺点,是否可以通过平衡
- 分类
- 时间和空间互换:例如deepseek中的KVcache缓存通过额外内存存储常用数据,减少重复计算的时间消耗
- 数量和质量互换:例如deepseek中的细粒度专家分割,将之前少量的大expert变成更多的小expert,从而降低过拟合程度,提高效率
- 横向分层和纵向分组:
- 分布式和中心化:
- 异构和多核
- 分类
- 逻辑和物理的映射
- deepseek中EBLP的负载均衡,物理专家多出逻辑专家的为冗余专家,用于调节逻辑专家的负载均衡
- 内存拓展:实际的物理内存存储常用的,多余的不常用的存放在物理磁盘,从而实现内存的拓展
- 最简功能验证
- 使用某框架下,最简单的示例程序验证框架功能的可行性,从而避免在复杂应用中无法排除问题
- llamafactroy的前端ui界面llama board无法实现运行,由于涉及程序过多无法排查原因,采用最简的gradio程序发现是gradio的CS服务启动连接问题导致的
- 适配工作
- 使用
稳定的版本进行适配,最新的版本往往存在隐藏的问题,在复杂系统中难以集成进来 - llamafactroy集成到aicp平台的,使用最新的v0.9.3dev发现一直存在版本依赖问题,最后发现v0.9.1可以直接集成(加班十天的血泪教训)
- 使用
- 一个工作要明确开始截至时间,并在过程中细化小任务的开始截至时间,从而明确评估
- 集权的优势
- 核心:通过
分离控制平面与数据平面,并在SDN控制器上集中控制,从而快速适应网络需求变化,按需分配资源 - 中央集权控制:中央集权获取的是地方策略的生成权,而不是实际的执行权
- 问题:分散的策略配置难以保持一致性,可能因为资源争用难以达到全局最优策略
- 解决:中央控制器以全局数据驱动策略生成,然后将一致的策略快速下发到各个网络设备,从而动态响应变化,并达到一个全局资源利用的最优决策,最终获得最大效益。
- 核心:通过
- 规划和实施
- 规划
- 核心是 “明确目标和约束”,确保行动不偏离核心需求,不纠结于具体细节
- 提出核心目标(第一性原理,解决什么问题),设定约束条件(不能突破的属性边界约束),监控偏差并纠偏
- 实施(Implementation)
- 怎么做(步骤)、用什么方法(工具)、如何解决细节问题(执行)
- 协同:实施需要反馈给控制相关信息,当控制发现在实施过程中出现问题,控制可能调整目标(比如 “接受环保颗粒板,预算不变”),再由实施继续执行 —— 这是 “控制 - 实施 - 反馈 - 调整” 的闭环。
- 例子
- 土木中的规划工程师和实施工程师,istio中的控制平面和数据平面
- 规划
- 从最小粒度开始排查
- 多机训练失败,先单机单卡验证基本功能,然后单机双开验证卡间通信,然后双机单卡验证机间通信,然后双机多卡验证,最后多机多卡验证
- 重构代码
- 重构代码应该建立在对过去代码和工作的全面理解上,而不是一开始就重构,这样即使重构也无法做出最大的优化
工作准则
- 代码提交
- 入库前,必须校验代码的有效性
- 提交时,将代码生产和缓存文件删除
- 版本引入新功能必须保持原依赖不变
- 示例:jupyterlab安装mindstdio会将jupyterlab强制切换到v4.0,从而导致其他依赖出现问题
思维火花
- 【idea】现代计算机体系结构是等级制的
- BIOS是上帝,CPU是世界的运行规则的掌管者,MBR是始皇帝,内核是太子/现在的皇帝。资本主义和共产主义模式的计算机体系结构是什么样的?共产系统中肯定用到许多助人为乐机制,拥有的资源多少是权力的本质。是否应该从解决问题的角度去构思,而不是数据+指令的方式
- 每个应用程序对应一个权限表,让这个应用程序可以直接相当于一直运行在内核态,不需要频繁的用户态和内核态的上下文切换
- 调度器是一个中央资源向下分配的问题,类似于集权式的国家。eg:发改委下拨100亿的经费,如何分配
- 中央集权控制:中央集权获取的是地方策略的生成权,而不是实际的执行权,让地方在有限制的博弈中完成目标
- 【idea】可编程逻辑阵列,将异构资源进行粒度的细化然后根据需求进行不同的调度,提高通用性和性能。
- 【idea】函数应该具有反馈和负向反馈机制,而不只是输入-计算-输出
- 【idea】无论是MCP还是Skill本质都是为了解决问题,而日常的运维实践方面,通常要在多个VPN和浏览器之间去实践操作,应该是aiIDE中封存各种支持的工具,如浏览器等,可以开启学习模型,从而学习一次用户的全程处理操作,然后将这个流程内化成更加准确的提示词,然后使用者再泛化其中的几个步骤,从而形成一个真正准确的技能
- 【idea】如何技术型领导如何确立地位,首先通过一个较复杂的但是,个人比较熟悉的项目给到员工,然后员工无法解决,在项目预留临期时,参与指导和处理,从而完成领导地位的确立