- 博客(66)
- 资源 (1)
- 收藏
- 关注
原创 Effective C++(七):inline关键字, 降低文件间依存关系
这个问题的根源出在编译器必须在编译期间知道对象的大小,如果看不到类的定义式,就没有办法为对象分配内存。这样,假如我们要修改Person的private成员,就只需要修改PersonImpl中的内容,而PersonImpl的具体实现是被隐藏起来的,对它的任何修改都不会使得Person客户端重新编译,真正实现了“类的接口和实现分离”。毫无疑问的是,句柄类和接口类都需要额外的开销,句柄类通过 Person 类中的指向PersomImpl的指针来获得对象数据,增加一层间接访问,指针大小和动态分配内存带来的开销;
2023-12-08 16:11:09
1007
原创 Effective CPP(五): 设计接口的原则
由于std::swap函数在 C++11 后改为了用std::move实现,因此几乎已经没有性能的缺陷,也不再有像原书中所说的为自定义类型去自己实现的必要。不过原书中透露的思想还是值得一学的。如果想为自定义类型实现自己的swap方法,可以考虑使用模板全特化,并且这种做法是被 STL 允许的:public:private:templatea.swap(b);
2023-12-07 16:31:58
1003
原创 Effective C++(四): 资源管理
为了防止忘记调用 delete 造成的内存泄露,我们应该尽可能让对象管理资源,并且采用 RAII 机制(Resource Acquisition is Initialize)机制,让析构函数负责资源的释放。
2023-12-02 23:01:21
993
原创 Effective CPP(三):类的构造/析构/赋值运算
如果在基类中定义了虚析构函数,在删除对象释放资源的时候,会首先调用派生类的析构函数,再调用基类的析构函数。假如第四点条款没有被遵守,在调用基类的构造函数以期望调用派生类中已经重写的虚函数的时候(比如使用基类的指针构造派生类),会意外执行到还没有被重写的虚函数。如果想要基类在构造的时候就得知派生类的构造信息,推荐的做法是在派生类的构造函数中将必要的信息向上传递给基类的构造函数。在创建派生类对象的时候,基类的构造函数会早于派生类的构造函数调用, 基类的析构函数会晚于派生类的析构函数被调用。
2023-12-02 20:27:17
880
原创 Effective C++(二):对象的初始化
这种做法的好处在于函数内的局部静态对象 td 会在该函数 tempDir被调用的时候被初始化,fs也只会在 tfs()被调用的时候被初始化,不仅让静态变量初始化的顺序可控,而且节省了资源,在没有必要创建他们的时候不进行类变量的创建。为了避免这种开销和潜在的线程安全问题,一种常见做法是在程序的单线程启动阶段(即在多线程被创建之前)手动初始化这些静态局部变量。这是由于 C++对于定义在不同编译单元中的全局静态对象的初始化的相对次序并没有明确定义,因此,下列代码可能会出现使用未初始化静态对象的情况。
2023-12-02 18:03:43
436
原创 Effective C++(一): Const Correctness, Const成员函数和Const Cast
有关 const 的用法是 cpp 中一个非常经典且易错的部分,在面试和日常工作中各种各样的 const 经常让人摸不着头脑,今天就来根据 const 扮演的不同角色来归纳有关 const 的不同用法。
2023-12-02 17:27:56
996
原创 TensorRT入门实战,TensorRT Plugin介绍以及TensorRT INT8加速
首先,根据上图可知,TensorRT是一个适配NVIDIA GPU的深度学习的推理框架,其能实现高性能深度学习推理,优化器和加速库,能够实现低延迟和高吞吐量,可以部署到超大规模的数据中心,嵌入式(Jetson)或者汽车产品。低精度优化: 比如INT8加速和FP16精度Kernel自动调优: 比如在cublas中对于矩阵乘法有多种实现,如何采取合适的矩阵乘法方式就是kernel自动调优。算子融合:比如原算子如下:融合后的算子如下:4. 多流运行5 显存优化。
2023-05-06 11:12:23
1536
原创 CUDA编程之矩阵乘法
对于平铺矩阵算法,对于每一个Block,首先将其存储在共享内存中, 花费 * Block_Size ^ 2,对BLock_SIze中每一个元素进行读取需要花费: 2 * k / Block_Size 个单位时间,一共有Block_Size ^ 2个元素, 一共有 (m * n) / (block_size * block_size)个Block,所以总时间就是这些值进行相乘。n])的矩阵乘法运算,每个线程都要读取A的一整行和B的一整列。• 共享内存属于线程块,可以被一个线程块内的所有线程访问。
2023-05-04 13:44:38
2658
原创 GPU基础与CUDA编程入门
预取是一种内存管理策略,旨在减少内存访问延迟,从而提高计算性能。预取机制通过预先加载数据到高速缓存(例如,从全局内存到共享内存或纹理内存)来实现这一目标,以便在执行计算任务时减少等待时间。GPU的预取机制有两种形式:硬件预取:这是由GPU硬件自动实现的预取机制,不需要程序员进行显式操作。GPU内部的内存控制器会预测内存访问模式,提前将可能需要的数据加载到高速缓存中。这种预取机制在许多现代GPU架构(如NVIDIA的Pascal、Volta和Ampere架构)中都有实现。
2023-05-04 10:07:35
2382
1
原创 C++采用Daemon进行后台程序的部署
通过调用fork()函数创建一个子进程。这将产生一个新的进程,该进程是原始进程的副本。对于子进程,fork()返回0,对于父进程,fork()返回子进程的进程id。在C++中,如果要让一个程序一直在后台运行并且和终端会话分离,我们可以将其作为守护进程运行,以下是创建C++守护进程的一般步骤。在子进程中,调用setsid()函数创建一个新的会话,这将使得子进程成为新会话的领导进程,并且摆脱原来的控制终端。使用chdir()函数来创建一个新的会话,这将使得子进程成为新会话的领导进程,同时摆脱原来的控制终端。
2023-04-26 15:37:04
745
原创 2023最新C++面经(一):vector内存预分配,左值引用和右值引用,move语义
今天在朋友圈看到别人发的一套C++面经,特意思考了一下。
2023-03-04 19:44:10
1677
原创 计算机网络(六): HTTP,HTTPS,DNS,网页解析全过程
服务端推送:服务器会在客户端没发起请求的时候主动推送一些需要的资源,比如客户端请求一个html文件,服务器发送完之后会把和这个html页面相关的静态文件也发送给客户端,当客户端准备向服务器请求静态文件的时候,就可以直接从缓存中获取,就不需要再发起请求了。410 表示所请求的资源已经被永久删除。header压缩:每次进行HTTP请求响应的时候,头部里很多的字段都是重复的,在2.0中,将字段记录到一张表中,头部只需要存放字段对应的编号就行,用的时候只需要拿着编号去表里查找就行,减少了传输的数据量。
2023-02-25 14:22:52
3156
1
原创 计算机网络(五):三次握手和四次挥手,TCP,UDP,TIME-WAIT,CLOSE-WAIT,拥塞避免,
当客户端发出最后的ACK确认报文时,并不能确定服务器能够接收到该段报文。所以客户端在发送完ACK确认报文之后,会设置一个时长为2MSL的计时器。如果服务器在1MSL后仍然没有收到客户端发送的ACK确认报文,那么它会向客户端重传FIN报文,对客户端而言,从客户端发出ACK报文起,重传的FIN报文的最晚到达时间是2MSL。若服务器在1MSL内没有收到客户端发出的ACK确认报文,再次向客户端发送FIN释放连接报文。
2023-02-23 13:45:49
431
原创 计算机网络(四):ICMP协议,ARP地址解析协议,NAT地址转换,TTL
该技术不仅能解决 IP 地址不足的问题,而且还能隐藏和保护网络内部主机,从而避免来自外部网络的攻击。ICMP是因特网控制报文协议,主要是实现IP协议中未实现的部分功能,是一种网络层协议。ARP是地址解析协议的缩写,该协议提供根据IP地址来获取物理地址的功能,其是一个链路层协议,其在链路层中和物理层进行联系同时向上层提供服务。当通过以太网发送IP数据报时,需要先封装32位的IP地址和48位的MAC地址。TTL指的是生存时间,简单来说,他表示了数据报在网络中的时间。
2023-02-23 12:27:22
944
原创 计算机网络(三):IP协议,路由器转发,路由器和交换机的区别
IP 数据报在传输过程中,每个中间节点(IP 网关、路由器)只根据网络地址进行转发,如果中间节点是路由器,则路由器会根据路由表选择合适的路径。分段与重组:IP 数据包在传输过程中可能会经过不同的网络,在不同的网络中数据包的最大长度限制是不同的,IP 协议通过给每个 IP 数据包分配一个标识符以及分段与组装的相关信息,使得数据包在不同的网络中能够传输,相比于TCP协议,IP 协议提供一种无连接/不可靠、尽力而为的数据包传输服务,其与TCP协议(传输控制协议)一起构成了TCP/IP 协议族的核心。
2023-02-18 15:47:16
1138
原创 计算机网络(二):物理层和链路层,通道复用,MAC地址,CSMA/CD协议,PPP点对点协议
如果我们的路由器需要记录下全世界的MAC地址的话,一共需要2的48次方(MAC地址是48位)的内存,也就是256T。而和MAC地址不同,IP地址是和地域相关的,在一个子网中的设备,我们给其分配的IP地址前缀都相同,这样路由器就能根据 IP 地址的前缀知道这个设备属于哪个子网,剩下的寻址就交给子网内部实现,从而大大减少了路由器所需要的内存。在数据的发送过程中,以太网是一直在监听信道的,当检测到当前信道冲突,就立即停止这次传输,避免造成网络资源浪费,同时向信道发送一个「冲突」信号,确保其它节点也发现该冲突。
2023-02-18 15:05:22
1146
原创 计算机网络(一):OSI七层模型,TCP/IP五层模型以及他们之间的异同
在最简单的情况下,运输层收取到报文并附上附加信息,该首部将被接收端的运输层使用。应用层报文和运输层首部信息一道构成了运输层报文段。运输层则向网络层传递该报文段,网络层增加了如源和目的端系统地址等网络层首部信息,生成了网络层数据报。该数据报接下来被传递给链路层,在数据链路层数据包添加发送端 MAC 地址和接收端 MAC 地址后被封装成数据帧,在物理层数据帧被封装成比特流,之后通过传输介质传送到对端。OSI七层模型包括应用层,表示层,会话层,传输层,网络层,链路层和物理层。
2023-02-18 14:52:00
1159
原创 MySQL(三):切分,主从复制,读写分离
当一个表的数据不断增多的时候,sharding是必然的选择,它可以将数据分布到集群的不同节点上,从而缓解单个数据库的压力。垂直切分指的是将一张表按列拆分成多个表,通常是按照列的关系密集程度进行切分,也可以利用垂直切分将经常被使用的列和不经常被使用的列进行切分到不同的表中。在数据库的层面使用垂直切分将按数据库中表的密集程度部署到不同的库中,例如将原来的电商数据库垂直切分成商品数据库、用户数据库等。1.binlog线程: 负责将主服务器上的数据更改写入二进制的日志。映射表:使用单独的一个数据库来存储映射关系。
2023-02-17 21:20:38
665
1
原创 MySQL(二):InnoDB和MyISAM
即:InnoDB 如果添加其他辅助索引,辅助索引查询就需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也相应都会很大。(比如表中有id(主键),name,age 字段,我们创建一个主键索引,再来创建一个name索引,层级关系如下图所示)InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的;MyISAM是非聚集索引,它也是使用B+Tree作为索引结构,但是索引和数据文件是分离的,索引保存的是数据文件的指针。
2023-02-17 17:21:57
536
原创 MySQL(二):查询性能分析
对于连接查询,如果其中一个表发生变化,那么整个查询缓存就无法使用。而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用。例如下面的例子中,使用 IN() 代替连接查询,可以让 MySQL 按照 ID 顺序进行查询,这可能比随机的连接要更高效。分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到,从而减少冗余记录的查询。在应用层进行连接,可以更容易对数据库进行拆分,从而更容易做到高性能和可伸缩。select_type : 查询类型,有简单查询、联合查询、子查询等。
2023-02-17 17:19:53
708
原创 MySQL(一):B+ Tree,索引以及其优点, 索引实战, 聚簇索引和非聚簇索引, 最左匹配,索引失效
在MySQL建立联合索引时会遵守最左前缀匹配原则,即最左优先,在检索数据时从联合索引的最左边开始匹配。由于构建一棵B+树只能根据一个值来确定索引关系,所以数据库依赖联合索引最左的字段来构建。举例:创建一个(a,b)的联合索引,那么它的索引树就是下图的样子。可以看到a的值是有顺序的,1,1,2,2,3,3,而b的值是没有顺序的1,2,1,4,1,2。但是我们又可发现a在等值的情况下,b值又是按顺序排列的,但是这种顺序是相对的。
2023-02-17 17:10:56
1875
转载 推荐算法中常用负采样策略
流行度越高的item受到用户喜爱的概率也越大,因此如果流行度高的item出现在负样本里可以认为它的信息量越大。1、曝光未点击行为不一定能代表user真正不感兴趣的信息,曝光未点击有可能的原因是user已经看过该内容或者准备下次再看,也有一些user不感兴趣的内容因为没有曝光而没有被采样到负样本里。1、除了采用曝光未点击数据作为负样本以外,也可以从召回结果中user未点击且未曝光的item作为负样本,这种全局采样的方法可以在一定程度上消除一些item由于没有曝光造成的样本偏差问题。1、平衡正负样本比例。
2023-02-16 19:32:24
996
原创 操作系统(四):磁盘调度算法,先来先服务,最短寻道时间优先,电梯算法
如果新到达的磁道请求总是比一个在等待的磁道请求近,那么在等待的磁道请求会一直等待下去,也就是出现饥饿现象。扇区(Track Sector):磁道上的一个弧段,一个磁道可以有多个扇区,它是最小的物理储存单位,目前主要有 512 bytes 与 4 K 两种大小;电梯算法(扫描算法)和电梯的运行过程类似,总是按一个方向来进行磁盘调度,直到该方向上没有未完成的磁盘请求,然后改变方向。磁头(Head):与盘面非常接近,能够将盘面上的磁场转换为电信号(读),或者将电信号转换为盘面的磁场(写);
2023-02-15 16:36:58
2397
原创 操作系统(三):内存管理,分页地址映射,页面置换算法LRU,NRU,FIFO,第二次机会算法和时钟算法
如果是 1,就将 R 位清 0,并把该页面放到链表的尾端,修改它的装入时间使它就像刚装入的一样,然后继续从链表的头部开始搜索。每一个程序拥有自己的地址空间,这个地址空间被分成多个页,并被映射到物理内存中(不需要连续),当程序引用到不在物理内存中的页的时候,由硬件执行必要的映射,并将缺失的部分装入物理内存中并重新执行之前失败的指令。程序的地址空间划分成多个拥有独立地址空间的段,每个段上的地址空间划分成大小相同的页。当页面被访问的时候设置页面的R = 1, 当页面被修改的时候设置M = 1。
2023-02-15 16:30:45
2091
原创 操作系统(二):死锁的检测,死锁的恢复和死锁的预防
有两个或者以上的进程的资源请求组成了一条环路,该环路中的每一个进程都在等待下一个进程所占有的资源。
2023-02-15 15:46:54
1088
原创 从零实现WebRTC(二):WebRTC的通信过程
ICE 基本思想,每一个代理拥有多种可用于与对端通信的候选传输地址(TRANSPORT ADDRESSES,针对特定传输协议(一般为 UDP 协议)的 IP 地址和端口的组合),ICE 通过不断地尝试以确定真正可用的传输地址对;WebRTC是一个集成了音视频通话中的多个应用的框架,主要是想尝试解决音视频通话中的一系列实时音视频应用问题,比如采集,编码,解码,前后处理,传输,缓冲,渲染,美颜,回声消除等等等等。媒体信息SDP用于描述在对等连接上传出的数据的信息,比如音频,视频和应用数据。
2023-02-14 22:16:46
814
原创 WebRTC服务器理论铺垫(六):OpenSSL协议,DTLS协议,RTP协议和SRTP协议
SSL的全名叫做secure socket layer(安全套接字层),最开始是由一家叫网景的互联网公司开发出来,主要是防止信息在互联网上传输的时候不被窃听或者篡改,后来网景公司提交SSL给ISOC组织做标准化,改名为TLS(transport layer security)。其实在互联网的数据传输中,对数据进行窃听和修改是非常容易的,如果你上网连得的是wifi,那么你的数据一定会经过wifi路由器,通过对路由器做些手脚就可以拿到这些数据。TLS是基于TCP协议的,DTLS是基于UDP协议的。
2023-02-13 15:49:27
1185
原创 数据库(六): MySQL的主从复制和读写分离
实现的方式有很多,比如采用Spring AOP的方式去判断输入的mysql语句,如果sql语句中包含get,select,query就去连接slave,否则就去连接master。比如说,假设是单机,读和写都在一台mysql上面完成,性能肯定不高,如果有三台mysql,一台master只负责写操作,两台slave负责读操作,性能不就可以大大提高了吗。sharding.master-slave-rules是标明主库和从库,一定不要写错,否则写入数据到从库,就会导致无法同步。假设我们有三台虚拟机。
2023-02-13 11:27:03
431
原创 从零实现高并发WebRTC服务器(五):ICE协议
如图,两个终端通过白云(信令服务器)进行建立连接。在建立连接之前需要通过STUN Server来进行NAT穿越,如果STUN Server 进行NAT穿越不成功就使用Relay Server。(协议,IP,端口和类型)。例如a = candidate …192.169.1.2 8080 typ host。ICE,interactive connectivity establishment. 即需要两端交互才能进行连接。
2023-02-12 23:39:52
370
原创 WebRTC(一):三种架构和基本原理
从上述 SFU 的定义可以看到,SFU 这种网络拓扑模型,通过由 SFU Server 来实现 one-to-many ,减轻了多人视频通话场景下每个客户端的上行带宽压力,但是下行依然是多路流,随着通话人数的增大,下行带宽的压力依然会成比例的增大,那能否让下行也只剩一路流呢?,受到更广泛的欢迎和应用,常见的开源 SFU 服务器有:Licode,Janus,Jitsi,mediasoup,Medooze 等等,各有特点,大家可以去项目主页了解更详细的情况。SFU 相比于 MCU,
2023-02-12 20:51:27
1291
原创 操作系统(一): 进程和线程,进程的多种状态以及进程的调度算法
本文转载于cyc大佬的cs notes,在摘抄的过程中添加了部分自己的理解多个并发进程在一些关键点上可能需要互相等待或互通消息,这种相互制约的等待或互通消息称为进程同步。
2023-02-12 20:08:36
779
转载 数据库(五):ER图
下图表示一个课程的先修关系,先修关系出现两个 Course 实体,第一个是先修课程,后一个是后修课程,因此需要用两条线来表示这种关系。虽然老师可以开设多门课,并且可以教授多名学生,但是对于特定的学生和课程,只有一个老师教授,这就构成了一个三元联系。用一个三角形和两条线来连接类和子类,与子类有关的属性和联系都连到子类上,而与父类和子类都有关的连到父类上。如果是多对多,画两个不带箭头的线段。本文转载于CYC CS Notes。如果是一对一,画两个带箭头的线段;包含一对一,一对多,多对多三种。
2023-02-12 19:06:31
1061
转载 数据库(四):函数依赖和数据库异常,第一范式,第二范式,第三范式,第四范式
本文转载于:https://zhuanlan.zhihu.com/p/20028672在阅读本文时,可以把“关系”理解为数据表。此外还有一个“关系模式”的概念。“关系”和“关系模式”的区别,类似于面向对象程序设计中”类“与”对象“的区别。”关系“是”关系模式“的一个实例,你可以把”关系”理解为一张带数据的表,而“关系模式”是这张数据表的表结构。
2023-02-12 17:41:32
2144
原创 Redis(七): 事务和事件
redis基于reactor模式开发了自己的网络事件处理器,使用IO多路复用程序来同时监听多个套接字,并将到达的事件传送给文件事件分排期,分排期会根据套接字产生的事件类型调用相应的事件处理器。服务器需要不断监听文件事件的套接字才能得到待处理的文件事件,但是不能一直监听,否则时间事件无法在规定的时间内执行,因此监听时间应该根据距离现在最近的时间事件来决定。Redis 将所有时间事件都放在一个无序链表中,通过遍历整个链表查找出已到达的时间事件,并调用相应的事件处理器。Redis服务器是一个事件驱动程序。
2023-02-11 23:38:19
303
原创 Redis(六):数据淘汰策略和键值对过期时间
但是对于散列表这种容器,只能为整个键设置过期时间(整个散列表),而不能为键里面的单个元素设置过期时间。Redis可以为每一个键设置过期时间,当键过期时,会自动删除该键。可以设置内存最大使用量,当内存使用量超出时,会施行数据淘汰策略。
2023-02-11 23:26:51
112
原创 数据库(四):多版本并发控制MVCC,行锁的衍生版本,记录锁,间隙锁, Next-Key锁(邻键锁)
MVCC,即多版本并发控制,是InnoDB机制中的一种用来解决读写冲突的无锁并发机制。我们可以简单认为MVCC式行锁的变种。在表锁中我们的读写是阻塞的,基于提升并发性能的考虑,MVCC一般读写是不阻塞的(很多情况避免了加锁的操作)。MVCC解决了脏读和不可重复读的问题,但是在某些情况仍然没有解决幻影读的问题。这就是为什么我们要引入接下来的邻键锁Next-Key Locks。
2023-02-11 17:35:20
599
原创 数据库(三):行锁和表锁,共享锁和排他锁,数据库引擎MyISAM和InnoDB,乐观锁和悲观锁
之前我们提到了数据库的隔离性可能会出现的若干问题,以及数据库为了解决这些问题而提出来的若干种隔离级别。实际上,数据库底层实现这些隔离级别的原理本质上就是通过各种封锁。今天我们在这里总结一下两种封锁粒度。
2023-02-11 17:11:51
1145
原创 C++面经(五):堆和栈的区别,malloc和new的区别,free和delete的区别
栈类似于街边的饭店,你去里面吃饭(申请里面的内存)只需要负责点菜,而不需要负责洗菜,切菜,炒菜,端盘,洗碗,收拾餐桌。优点是你吃饭的过程是连续的(栈的内存是连续的), 但是缺点是你可以选择的范围比较小(栈空间的内存比较小),而且越吃你的钱越少(栈内存往低地址扩展)。堆类似于自家的厨房,你在里面吃饭,需要一个人负责点菜,洗菜,切菜,炒菜,端盘,洗碗和收拾餐桌。
2023-02-10 14:44:45
140
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人