- 博客(49)
- 收藏
- 关注
原创 高并发内存池
本项目实现的是一个高并发的内存池,它的原型是Google的一个开源项目tcmalloc,tcmalloc全程Thread-Caching Malloc,即线程缓存的malloc,实现了高效的多线程内存管理,用于替换系统的内存分配相关函数malloc和free。 tcmalloc的知名度也是非常高的,不少公司都在用它,比如Go语言就直接用它做了自己的内存分配器。该项目就是把tcmalloc中最核心的框架简化后拿出来,模拟实现一个mini版的高并发内存池,目的就是学习tcmalloc的精华。
2025-03-20 11:12:57
844
1
原创 I/O多路转接——select、poll、epoll
epoll有三个相关的系统调用,分别是epoll_create、epoll_ctl和epoll_wait。
2024-10-21 21:45:55
1332
原创 Linux高级I/O
I/O我们并不陌生,简单的说就是输入输出; 对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达,然后被复制到内核的某个缓冲区;第二步就是把数据从内核缓冲区复制到应用进程的缓冲区。 注:我们以UDP数据报为例,来介绍这五个模型,主要是因为,数据准备好读取的概念比较简单,要么整个数据报已经收到,要么还没有。对于TCP而言,它是面向字节流的,存在水位线的概念,导致理解起来比较复杂。 接下来我们都会先以一个简单的生活例子来解释这五种I/O模型,然后再对图例进行解释;
2024-10-19 10:13:05
798
原创 C++模板初阶
class 类模板名{// 类内成员定义 当我们想用栈来存储不同类型时,我们常用的是将类型(int,char…)进行typedef,但是在同一个程序中当你想要在创建的第一个栈中存储int,创建的第二个栈存储char时,是做不到的;针对这种情况C++引入类模板。int _size;/* STL 标准普通类:类名和类型是一样类模板:类名和类型不一样*/
2024-10-05 15:54:20
890
原创 C++内存管理
作为一名程序员,良好的代码风格,是最基本的素养。内存泄漏不是一件小事,做好每一步的措施,要时时刻刻提醒自己;以上是对C/C++中内存管理的大致概括。
2024-10-05 14:55:14
1153
原创 C++类和对象下
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态的成员变量一定要在类外进行初始化;++_scount;//没有this指针,只能访问静态的成员变量和成员函数private:int _a;//静态成员变量属于整个类,所有对象,生命周期在整个程序运行期间,类的成员函数中可以随便访问。
2024-10-04 22:46:06
721
原创 C++类和对象(中)
如果类中没有显示定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显示定义构造函数编译器将不再生成。简单的讲就是,你觉得编译器默认生成的构造函数不是你想要达到的效果,你就自己定义(显示定义),你觉得编译器默认生成的构造函数够用了,满足条件,就不用自己定义了(未显示定义);/*如果没有显示定义构造函数,会发生什么情况呢*/public:/*未显示定义构造函数*/private:int _year;int _month;int _day;Date d1;
2024-10-04 11:58:49
1004
原创 C++类和对象(上)
上图中的struct类,在C++中更喜欢用class来代替;// 类体:由成员函数和成员变量组成// 一定要注意后面的分号 class为定义类的关键字,className为类的名字,{}中为类的主体,注意类定义结束时后面分号。类中的元素称为类的成员;类中的数据称之为类的属性或者成员变量;类中的函数称之为类的方法或者成员函数。struct Student { //成员变量int _age;int _id;//成员方法/成员函数_age = age;_id = id;
2024-09-30 21:04:56
825
原创 C++快速入门
定义命名空间,需要使用namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。int a = 10;int& b = a;//--定义引用类型//引用在语法层,我们要理解这里没有开新的空间,就是对原来的取了一个新的称叫做b//--这里是取地址ba = 20;b = 30;//a改变了,b也会改变;b改变了,a也会改变return 0;//不可以作参数//不可以定义数组return 0;
2024-09-30 16:18:41
1079
原创 【C++11】线程库
在C++11之前,涉及到多线程的问题,都是和平台相关的,比如windows和Linux下各自有自己的接口,这使得代码的可移植性比较差,C++11中最重要的特性就是对线程进行了支持了,使得C++在并行编程时不需要依赖第三方库,而且在原子操作中还引入了原子类的概念。要使用标准库的线程,必须包含 头文件。
2024-09-26 22:27:31
1105
原创 git学习【完结】
情况3:版本库存在最新版本的代码 xxx code,但是上一版不包含 xxx code,我们通常使用git进行版本控制的流程如下:工作区->(git add)->暂存区->(git commit)->版本库->(git push)->远程仓库,我们情况3撤销的前提是在commit之后没有进行push,撤销的目的就是不要影响远程仓库的代码。 因为创建,合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。
2024-09-18 11:32:01
1091
1
原创 【C++11】包装器
function包装器 也叫做适配器。C++中的function本质是一个类模板,也是一个包装器。function的作用是将具有相同调用形式的不用类型的可调用对象进行类型统一。
2024-09-17 09:02:51
917
原创 【C++11】lambda表达式
在给定的商品类中,如果我们想要通过名字、价格和评价来给商品进行升序或降序。 显然这样写是没有什么问题,但是,如果你写的仿函数在取名的时候不是很贴切,导致他人看你写的仿函数的时候,有可能看不懂,我们来看看lambda表达式写出来是什么样子的; 这样一来,每次调用sort函数时只需要传入一个lambda表达式指明比较方式即可,阅读代码的人一看到lambda表达式就知道本次排序的比较方式是怎样的,提高了代码的可读性。
2024-09-16 21:05:39
1050
原创 【C++11】可变参数模板
在C++11之前,类模板和函数模板只能含有固定数量的模板参数,c++11增加了可变模板参数特性:允许模板定义中包含0到任意个模板参数。声明可变参数模板时,需要在typename或class后面加上省略号“…”。 现在调用ShowList函数时就可以传入任意多个参数了,并且这些参数可以是不同类型的。 我们可以在函数模板中通过sizeof计算参数包中参数的个数。
2024-09-16 15:41:51
1183
原创 leetcode hot100刷题【持续更新】
给定一个整数数组nums和一个整数目标值target,请你在该数组中找出target的那整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。你可以按任意顺序返回答案。**进阶:**你可以想出一个时间复杂度小于O(n2)的算法吗?:暴力枚举,没啥好说的:哈希表标注答案:一边赋值一遍计算。
2024-09-15 09:19:16
470
原创 leetcode 刷题周报(9.3-9.10)
给你一个下标从开始的整数数组nums,它表示一个班级中所有学生在一次考试中的成绩。老师想选出一部分同学组成一个小组,且这个小组的最大,如果这个小组里的学生下标为i0i1i2, … ,ik,那么这个小组的实力值定义为。请你返回老师创建的小组能得到的最大实力值为多少。
2024-09-10 10:38:37
725
原创 Vision Transformer(ViT)模型原理及PyTorch逐行实现
这样就构造出了一个n+1长度的序列,然后我们再加入position embedding,加上后的这个序列的表征就可以送入到TRM的encoder当中,最后取出结果中的我们加入的可训练的embedding位置上的值(输出状态),经过一个MLP,得到各个类别的概率分布,再通过一个交叉熵函数算出分类的loss,这样就完成了一个ViT模型的搭建。 提问:本身cls_token_embedding没有和任何样本矩阵有乘法联系,最后训练出来的也是一张确定的表,在做inference的时候,完全是一个常数的作用。
2024-09-08 11:22:40
1698
1
原创 Transformer从零详细解读
残差的原则就是输出至少不比输入差!多进行一个加法操作。 我们看下面一张图: 每一行代表一个特征,每个人的“体重,身高”等指标,每个人的第一个特征都是“体重”。x1,x2分别代表不同的人。
2024-09-07 22:27:09
1027
原创 【C++11】类的新功能
执行上面的代码,编译器会提示Person类没有默认的构造函数,在类和对象章节,我们知道对于构造函数,是这样定义的,我们不写编译器会默认生成一个构造函数,如果写了则不会生成。 两次运行结果不同的原因就在于,移动构造是一个特殊的默认成员函数,s1是一个左值,通过move函数,转变了性质,变成了右值属性,赋值给了Person s2,按照正常的逻辑应该会去调用s2的移动构造,然后去调用s1的移动构造; 默认生成的构造函数,对于自定义类型的成员会调用其构造函数进行初始化,但并不会对内置类型的成员进行处理。
2024-09-07 16:18:54
1193
原创 Pytorch多GPU分布式训练代码编写
Pytorch多GPU分布式训练代码编写一、数据并行1.单机单卡模型拷贝model.cuda() 原地操作数据拷贝(每步)data=data.cuda() 非原地操作基于torch.cuda.is_available()来判断是否可用模型保存与加载torch.save 来保存模型、优化器、其他变量torch.load(file.pt,map_location=torch.device(“cuda”/“cuda:0”/“cpu”))实际演示:环境检
2024-09-07 10:02:04
1133
原创 【C++11】右值引用和移动语义
需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可以取到该位置的地址,也就是说例如:不能取字面量10的地址,但是rr1引用后,可以对rr1取地址,也可以修改rr1。 右值引用和万能引用的区别就是,右值引用需要是确定的类型,而万能引用是根据传入实参的类型进行推导,如果传入的实参是一个左值,那么这里的形参t就是左值引用,如果传入的实参是一个右值,那么这里的形参t就是一个右值引用。(这个不能是左值引用返回)等等,右值可以出现在赋值符号的右边,但是不能出现在赋值符号的左边,
2024-09-06 09:48:12
1171
原创 【C++11】新特性入门
在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98成为C++11之前的最新C++标准名称。不过由于TC1主要是对C++98标准的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯的把两个标准合称为C++98/03标准。从C++0x到C++11,C++标准10年磨一剑,第二个真正意义上的标准姗姗来迟。
2024-09-05 16:07:55
1103
原创 MONAI入门介绍
MONAI (Medical Open Network for AI) 是一个专注于医疗图像处理的深度学习框架。下面我们将介绍如何使用 MONAI 进行数据预处理、DataLoader 构建、模型训练以及推理。: 是一个列表,每个元素是一个字典,包含了训练集中每个样本的图像和对应的标签文件路径。例如,表示第一个样本的图像文件路径,表示对应的标签文件路径。val_files: 类似于,包含了验证集中每个样本的图像和标签文件路径。DiceLoss。
2024-07-28 16:09:24
2432
原创 PyQt5 快速入门
因为我们后面需要对程序进行打包,所以为了减少对于打包没有帮助的库,我们创建一个干净的全新的虚拟环境进行开发。我这里是依赖于anaconda来创建虚拟环境,指令如下。 创建好之后,我们通过pip list指令来确认一下,发现确实是一个干净的环境。
2024-07-22 00:37:19
1265
1
原创 基于Resent的医学数据集分类实战
原始数据集:NCT-CRC-HE-100K:结肠癌组织NIH-ChestXray14 dataset:肺部X光数据HAM10000:皮肤病变数据集 但是这些数据集的规模都太大了,所以我们对这些数据进行处理,得到简易实验的数据集,所有的数据格式都类似mnist(28*28),方便我们进行初步试验。
2024-07-19 15:08:31
1375
原创 项目:文档扫描OCR识别
下图右边是输入图像,左边是通过边缘检测后的输出图像。我们需要关注的是图片的主题而不是背景,我们需要识别到我们要检测的主题。
2024-07-17 15:57:48
722
原创 Linux应用层协议HTTP(二)
平时我们俗称的“网址”其实就是说的URL(统一资源定位符,它是URI(统一资源标识符)的一个子集,是URI概念的一种实现方式);IP+端口可以定位互联网上唯一一台主机,但如果我们还需要该主机上的资源文件,还要有路径。即我们通过IP+路径,就可以唯一地确认一个网络资源。http、https协议或其他指定用户名和密码作为服务器端获取资源时的必要信息,此项为可选项,浏览器显示时会隐藏访问服务器时必须指明服务器地址,上图给出的只是方便人们记忆的网址,实际会由DNS(域名解析器)进行解析。
2024-06-29 20:33:41
878
原创 Linux应用层协议HTTP(一)
一般来说将这种结构化的数据发送给李四,是需要经过特殊处理的,那就是序列化,转变为一个长字符串;通过网络传输之后,再次经过反序列化的过程,填入李四的结构化数据相应的位置。 协议是一种“约定”,socket api的接口,在读取数据时,都是按“字符串”的方式来发送接收的,如果我们要传输一些“结构化的数据”怎么办呢?我们就需要对结构化的数据进行打包,然后通过网络发送至对端主机,再进行解包,进而对端主机接收到结构化的数据; 反序列化:将网络中的字节序列(可以理解为是长的“字符串”)转化为结构化的数据;
2024-06-29 20:29:19
736
原创 Linux基本的UDP套接字编程
在使用TCP编写的应用程序和使用UDP编写的应用程序之间存在一些本质的差异,其原因在于这两个传输层之间的差别:UDP是无连接不可靠的数据报协议,非常不同于TCP提供的面向连接的可靠字节流。 以下给出了典型的UDP客户/服务器的函数调用。客户不与服务器建立连接,而是只管使用sendto函数给服务器发送数据报,其中必须指定目的地(即服务器)的地址作为参数。类似的,服务器不接受来自客户端的连接,而是只管调用recvfrom函数,等待来自某个客户的数据到达。
2024-06-29 20:27:35
629
原创 Linux基本的TCP套接字编程(详解)
因此,它也被称为程序地址。 这么看来sockaddr_in这个结构也不复杂,除了一开始的2个字节表示sin_family,然后是2个字节的变量sin_port表示端口,接着是4个字节的变量sin_addr表示IP地址,最后是8个字节变量sin_zero填充尾部,用来与结构sockaddr对齐。 从介绍的套接字函数接口来看,bind函数,accept函数和connect函数都要一个struct sockaddr的结构体指针,我们在介绍参数的时候也已经说了,这种结构是指向一个特定于协议的地址结构的指针。
2024-06-29 14:51:00
829
原创 Linux网络基础(一)
今天我们开始接触计算机网络相关的知识,总的来说计算机网络的学习相比计算机操作系统的学习两者不相上下,如果你已经对操作系统有一定的知识体系,那么学习计算机网络将会变得很轻松。这是网络基础的第一章,里面涉及的新名词不会详细的介绍,会在后续更新的博客中详细介绍。
2024-06-29 14:44:34
757
原创 Linux线程池
线程池是线程的一种使用模式。在前面的情况中,我们都是遇到任务然后创建线程再执行。但是线程的频繁创建就类似于内存的频繁申请,会给操作系统带来更大的压力,进而影响整体的性能。 所以我们一次申请好一定数量的线程,然后将线程的管理操作交给线程池,就避免了在短时间内不断创建与销毁线程的代价,线程池不但能够保证内核的充分使用,还能防止过度调度,并根据实际业务情况进行修改。
2024-06-29 14:40:45
602
原创 Linux信号量
之前,我们利用加锁解锁保证了每次只有一个线程进入临界资源,但是临界资源很多也很大,如果每次只允许一个线程进入临界资源往往会使效率很低。但是将临界资源划分为多个独立的区域,划分为多少个区域就可以让多少个线程进入。信号量可以理解为一个计数器,它是用来描述临界资源的有效个数;
2024-06-29 14:39:02
920
原创 Linux生产消费者模型
处于生产者与消费者之间的缓冲区可以有多种实现方式,比较经典的就如阻塞队列(Blocking Queue)。如下图当队列为空时,消费者将会被阻塞,直到队列中存放了数据;当队列满时,生产者就会被阻塞,直到有数据取出;
2024-06-29 14:36:08
589
原创 Linux线程安全
但是由于线程A加锁的能力特别强,可能1000次中有900次是A加锁成功了,但是即便加锁成功了这么多次,对于A也是没有意义的,因为A加锁之后要对数据进行修改,然后让B操作,但是在这种情况下,B被阻塞了很多次,所以虽然数据是安全的,但是效率却十分低下,没有完成我们逻辑中按顺序执行的效果。 例如,我们在上述的抢票系统中引入互斥量,每一个线程要进入临界区之前都必须先申请锁,只要申请到锁的线程才可以进入临界区对临界资源进行访问,并且当线程出临界区的时候需要释放锁,这样才能让其余要进入临界区的线程继续竞争锁。
2024-06-29 14:33:13
1043
原创 Linux多线程
从运行结果以及进程监视脚本来看,新线程在分离后的2秒中后,自动退出了,主线程在等待新线程,并且想要获取到它的退出码”111“,但是结果确是0,所以新线程在设置分离后,主线程就不能再去join,会失败,它的资源会被自动回收;Linux中没有真正意义上的线程,它是用进程来模拟实现的,内核提供LWP,用户使用的线程要由线程库自己来管理,如何管理?操作系统中存在大量的进程,一个进程内又存在一个或多个线程,因此线程的数量一定比进程的数量多,当线程的数量足够多的时候,很明显线程的执行粒度要比进程更细。
2024-06-29 14:29:58
710
原创 Linux进程信号
函数功能:设置某一信号的对应动作第一个参数signum:指明了所要处理的信号类型,它可以取除了SIGKILL(9号信号)和SIGSTOP(19号信号)外的任何一种信号。第三个参数handler:表示我们要对信号进行的处理方法,它可以取以下三种值:关联动作含义SIG_DFL执行该信号的默认处理动作SIG_IGN忽略该信号提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数,这种方式称为捕获(catch)一个信号。
2024-06-29 14:27:14
897
原创 Linux进程间通信
进程通信(Interprocess communication),简称:IPC;本来进程之间是相互独立的。但是由于不同的进程之间可能要共享某些信息,所以就必须要有通讯来实现进程间的互斥和同步。比如说共享同一块内存、管道、消息队列、信号量等等就是实现这一过程的手段,相当于移动公司在打电话的作用。管道分为匿名管道和命名管道;管道通信方法的中间介质的文件,通常称这种文件为管道文件;匿名管道:管道是半双工的,数据只能单向通信;需要双方通信时,需要建立起两个管道;
2024-06-29 14:24:01
700
原创 Linux动态库和静态库
静态库在可执行程序链接时就加入到可执行代码中,在物理上称为可执行程序的一部分;程序运行时不再需要该静态库。相对于动态库链接生成的程序,静态库相当于编译器将代码补充完整了,因此执行程序会大一些,但是运行起来相对快些;静态库是牺牲了空间效率,换取了时间效率动态库在程序编译时并不会被链接到目标代码中,而是在程序运行时才被载入,因此在程序运行时还需要动态库存在;动态库只有在程序执行时,那些需要的函数才被拷贝到内存中。这样就使得可执行文件比较小,节省磁盘空间;
2024-06-29 14:12:44
946
原创 Linux基础IO
我们之前都有学过文件操作相关的函数,能够利用C语言相关的库函数进行文件的写入和读取;我们只是会用相关的库函数接口,但是并不知道文件究竟是怎么被写入的,怎么被读取的,文件操作的底层原理究竟是什么我们一概不知,接下来将会详细介绍文件操作的底层原理。让我们对文件操作有一个新的认识。函数接口函数说明fopen打开文件fclose关闭文件fputc一次写一个字符fgetc一次读一个字符fputs写一行数据fgets读一行数据fprintf格式化输出函数fscanf格式化输入函数。
2024-06-29 14:02:02
926
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人