超越POSIX:一个时代的终结?
在本文中,我们通过对Portable Operating System Interface(POSIX)抽象的历史演变进行系统性的回顾,提供了一个全面的视图。我们讨论了推动这些演变的一些关键因素,并确定了在构建现代应用程序时使它们不可行的缺陷。
POSIX标准定义了类Unix操作系统的接口。Unix是由程序员编写给程序员的第一个操作系统,而POSIX使开发人员能够编写可在不同的Unix操作系统变体和指令集架构上运行的可移植应用程序。Unix的主要应用场景是对存储(文件系统)进行多路复用,并为用户提供交互式环境(shell)。相比之下,许多当代基于POSIX的系统的主要应用场景是在数据中心的计算机上运行的服务,这些服务具有数量级较低的延迟要求。由于登纳德缩放定律(Dennard Scaling)在2004年前后结束,这些服务不能指望随着CPU时钟频率的增加而逐年运行得更快,因为CPU时钟频率不再以Unix普及时期普遍存在的速度增长。此外,许多人认为摩尔定律(Moore’s Law)正在放缓,因此软件不再能指望通过硬件优化的增加来变得更快,这是由于晶体管密度的增加所驱动的。随着我们迈向后摩尔定律时代的计算,系统设计师开始利用快速可编程网卡(NICs)、专用硬件加速器和非易失性主存等设备来应对应用程序的严格延迟限制。
年份 | 抽象 | 示例接口 | 版本 |
’69 | Filesystem | open, read, write | V0 |
’69 | Processes | fork | V0 |
’71 | Processes | exec | V1 |
’71 | Virtual memory | break1 | V1 |
’73 | Pipes | pipe | V3 |
’73 | Signals | signal | V4 |
’79 | Signals | kill | V7 |
’79 | Virtual memory | vfork2 | 3BSD |
’83 | Networking | socket, recv, send | 4.2BSD |
’83 | I/O multiplexing | select | 4.2BSD |
’83 | Virtual memory | mmap3 | 4.2BSD |
’83 | IPC | msgget, semget, shmget | SRV1 |
’87 | I/O multiplexing | poll | SRV3 |
’88 | Virtual memory | mmap | SunOS 4.0 |
’93 | Async. I/O | aio_submit | POSIX.1b |
’95 | Threads | pthread_create | POSIX.1c |
POSIX抽象和接口的时间线
这些抽象是在1970年代至1990年代的不同Unix变体中引入的。文件系统和进程是早期接口中的基本部分,已经存在于V0中。虚拟内存在1970年代的3BSD中引入,并在1980年代的4.2BSD和SunOS 4.0中完成。网络支持是在1980年代的4.2BSD中添加的。异步I/O和线程是在1990年代的POSIX标准中引入的。
-
break系统调用后来被重命名为brk,并添加了另一个变体sbrk。现在这两个都已被弃用。
-
3BSD添加了对基于页面的虚拟内存的支持。它们添加了vfork系统调用,以避免实现fork的写时复制。
-
尽管mmap是在1983年设计的,但提议的设计在1986年完全实现了。
POSIX的演进
POSIX的抽象(进程、文件系统、虚拟内存、套接字和线程)是基于不同Unix变体在1970年代和1980年代的开发中的操作系统抽象,例如Research Unix、System V、BSD、SunOS等。
它们各自时代的应用场景和硬件能力影响了这些抽象。例如,早期的Unix运行在PDP-11/20上,这是一台16位计算机,具有单个CPU和最多248KB的主存储器。由于PDP-11/20缺乏内存保护,Unix不支持虚拟内存,这与当时的其它操作系统(如Multics)不同。虽然后来的PDP-11变体,如PDP-11/70,具有内存映射单元(MMU),但直到1970年代末VAX架构的出现,Unix才添加了虚拟内存,这成为当时Unix的主要架构。同样,Unix直到1980年代初互联网出现后才有了网络抽象,当时的4.2BSD引入了套接字抽象,用于抽象TCP/IP网络协议进行远程进程通信。类似地,Unix直到1990年代初多处理器机器变得更加主流时才有了线程抽象。
文件系统
文件系统是一种访问和组织存储设备上字节数据的抽象。这种抽象及其I/O接口在很大程度上起源于Multics,并且被认为是Unix中最重要的抽象。然而,与Unix仅支持同步I/O不同,Multics还支持异步I/O,,这个特性最终成为了POSIX的一部分。
文件系统抽象还包括文件、目录、特殊文件以及硬链接和符号链接。文件系统中的文件是一系列字节,操作系统不以任何方式解释这些字节。这使得操作系统可以将硬件设备表示为特殊文件,并且操作文件的接口已经成为I/O设备的事实标准接口。
文件系统抽象可以方便地集成I/O设备。然而,它可能成为快速I/O设备的瓶颈。
进程
进程是系统中执行应用程序的抽象。具体而言,应用程序被表示为一个映像,抽象了其执行环境,其中包括程序代码(文本)、处理器寄存器值和打开的文件。此映像存储在文件系统中,操作系统确保进程映像的执行部分驻留在内存中。进程抽象自早期的Unix开始存在,并且对于共享计算和I/O资源的时间共享至关重要。
这种抽象根植于多道程序设计,这是一种在1950年代中期开发的技术,用于提高硬件利用率同时进行I/O操作。早期运行在PDP-7上的Unix仅支持两个进程,一个用于连接到机器的每个终端;后来设计为在PDP-11上运行的Unix可以将多个进程保留在内存中。
进程是一种以处理器为中心的抽象,对于假设进程映像的执行仅在CPU上完成的应用程序非常有用。然而,图形处理单元(GPU)、张量处理单元(TPU)和各种其它用于卸载计算的专用加速器等硬件设备的普及正在挑战这种假设。
相关视频推荐
c++八股文重点,网络的posix api实现原理
初识linux内核,进程通信还能这么玩
8个方面讲解io_uring,重塑对异步io的理解
免费学习地址:c/c++ linux服务器开发/后台架构师
需要C/C++ Linux服务器架构师学习资料加qun812855908获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享
虚拟内存
虚拟内存是一种抽象,可以创建一个看似与存储空间一样大的内存空间。它源于自动利用主内存速度和廉价存储容量的需要。虚拟内存的概念可以追溯到1960年代初:基于页面的虚拟内存最早出现在Atlas Supervisor中(1962年),Multics也支持虚拟内存。
虚拟内存是在Unix中添加的,大约在Unix诞生后的十年。在诞生时,Unix进程地址空间被划分为三个段:一个程序文本(代码)段,在所有进程之间共享但不可写;一个进程数据段,可读/写但私有;以及一个栈段。sbrk系统调用可以扩展和收缩进程数据段。然而,由于需要运行需要比当时主存储器容量更多的存储的程序(例如Lisp),VAX-11体系结构中的MMU使基于页面的虚拟内存成为可能。
这种抽象解耦了两个相关的概念:地址空间,即用于寻址内存的标识符,以及内存空间,即用于存储数据的物理位置。从历史上看,这种解耦具有三个主要目标:(1)通过独立于物理内存空间的地址空间促进机器的独立性,(2)通过允许程序员在执行时将独立的模块组合成程序来促进模块化,(3)实现运行大型程序的可能性,这些程序无法适应物理内存(例如Lisp程序)。虚拟内存的其它好处包括运行任意大小的程序、运行部分加载的程序以及更改内存配置而无需重新编译程序。虚拟内存被视为一种基本的操作系统抽象,但当前的硬件和应用趋势正在挑战其核心假设。
进程间通信(IPC)
进程间通信的抽象允许一个或多个进程相互交互。早期的Unix版本支持信号和管道。信号使程序员能够以编程方式处理硬件故障,并且该机制被泛化以允许一个进程通知其它进程。例如,shell进程可以使用信号来停止其它进程。管道是特殊的文件,允许进程彼此交换数据。管道不允许任意进程交换数据,因为两个进程之间的管道必须由它们共同的祖先进程建立。
由于管道和信号的限制,BSD添加了套接字以为本地和远程进程提供统一的IPC机制,即在不同主机机器上运行的进程之间的通信。套接字已成为网络的标准方式,但与平台特定的本地IPC机制相比,它们并未被广泛使用。
共享内存的mmap接口被设想为一种IPC机制,但从未真正普及。附加的IPC机制(信号量、专用于共享内存的IPC接口和消息队列)在POSIX.1b中被添加,于1993年发布,但此后主要被供应商特定的IPC机制所取代。
线程和异步I/O
线程和异步I/O是POSIX中为满足并行性和并发性需求的后来者抽象。
传统的UNIX进程提供单个执行线程。这种无法支持并发执行线程的能力使得单个UNIX进程无法利用多个计算核心提供的并行性。利用并行性的一种方法是分叉多个进程,但这要求分叉的进程使用IPC机制进行通信,这反过来效率低下。
POSIX异步I/O(AIO)接口旨在满足对非阻塞I/O接口的需求,从而改进并发性。该接口使进程能够调用异步执行的I/O操作。但在各种情况下它可能会阻塞,并且每个I/O操作需要至少两个系统调用:一个用于提交请求,另一个用于等待其完成。
在POSIX中,线程于1990年代初开始出现,是为了支持多核硬件的并行性并实现应用级并发性。与进程不同,线程在相同的地址空间中运行。POSIX线程可以以不同的方式实现:1对1:每个线程在自己的内核线程中运行;N对1:所有线程在单个内核线程中运行;N对M:N个线程在M个内核线程中运行。在用户空间中管理并行性对于高性能至关重要。然而,主流的POSIX操作系统采用了1对1的线程模型,理由是实现简单。尽管如此,使用大量线程的应用程序体系结构,如分阶段事件驱动架构(SEDA),由于线程开销的缘故效率低下。因此,许多高性能应用程序采用每个核心一个线程的模型,其中线程数量等于处理核心数量,并且提供自己的并发接口。
超越POSIX
计算卸载
POSIX进程是以CPU为中心的抽象,因为CPU在Unix发展的几十年中一直是中心和主要的计算资源。然而,将计算从CPU卸载到特定领域的协处理器和加速器(例如用于图形和并行计算的GPU,以及用于卸载数据包处理的NIC)已成为主流。因此,CPU越来越成为协调计算资源的协调器,并且CPU的计算能力越来越多地被应用程序用于仅在各种硬件资源上协调计算。
然而,POSIX没有机制来处理协处理器或加速器。因此,所有不是CPU的计算元素都被视为I/O设备。因此,应用程序需要使用用户空间API将代码和数据上传到加速器,该API通过不透明的系统调用(例如fcntl())与操作系统内核集成。例如,有用于GPGPU的OpenCL和CUDA,以及用于图形编程的Vulkan等API。这些API必须处理诸如内存和资源管理等事物,因为POSIX本身不支持这种类型的硬件。
缓存 | 同步 | 拷贝 | 复杂度 | |
read/write | kernel | yes | yes | low |
mmap | kernel | yes | no | medium |
DIO | user | yes | no | medium |
AIO/DIO | user | no | no | high |
io_uring | kernel/user | no | yes/no | high |
Linux中的I/O访问方法
异步I/O
异步I/O起源于Multics。然而,POSIX I/O调用起源于Unix,其I/O接口是同步的。因此,POSIX的read/write系统调用是同步的,并且它们会导致从内核页缓存中复制数据。同步接口对于快速I/O来说是一个瓶颈,并且需要应用程序使用线程来实现应用级并发和并行性。相比之下,mmap接口比传统的read/write更快,因为它避免了系统调用开销和内核与用户空间之间的数据复制。然而,使用mmap的I/O是同步的,具有更复杂的错误处理。例如,磁盘已满时,写入将返回错误代码,而基于mmap的I/O则需要处理信号。相比之下,直接I/O(DIO)允许应用程序使用相同的read和write系统调用,同时绕过页缓存。但是,缓冲区管理和缓存是在用户空间中执行的。异步I/O(AIO)接口提供了一组新的系统调用,允许用户空间应用程序异步提交I/O请求,并使用io_submit系统调用轮询I/O完成。然而,Linux的AIO实现存在一些问题:每次系统调用会复制高达104字节的描述符和完成元数据,并且系统调用有时会发生阻塞。
Linux的io_uring接口旨在解决这些缺陷,并提供真正的异步I/O接口。它首次引入于Linux内核5.1版本,使用两个无锁的单生产者单消费者(SPSC)队列在内核和用户空间之间进行通信。一个队列用于I/O提交,应用程序写入,内核读取,而另一个队列用于I/O完成,内核写入,应用程序读取。根据应用场景,应用程序可以配置io_uring实例以作为中断驱动、轮询或内核轮询来运行。io_uring接口允许线程提交I/O请求并在操作系统通知I/O操作完成前继续执行其它任务。
绕过POSIX I/O
POSIX I/O模型假设内核执行I/O,将数据传输到用户空间进行进一步处理。然而,这个模型在高到达率下不是很好扩展,所以早期绕过POSIX I/O接口的一个例子是BSD数据包过滤器(BPF,BSD Packet filter)。BPF通过在运行于内核中的伪机器内部过滤数据包来促进用户级别数据包捕获。数据包捕获应用程序首先命令内核复制到达网络接口卡(NIC)的数据包:其中一份复制遍历网络协议栈,而另一份遍历伪机器。BPF伪机器在将经过高级描述语言编译的数据包过滤代码发送到用户空间之前执行。扩展的伯克利数据包过滤器(eBPF,Extended Berkeley Packet Filter)在BPF的基础上构建,并允许应用程序在内核虚拟机中执行沙箱程序,或在能够运行这些程序的硬件上执行。这使得应用程序可以将I/O活动(例如网络协议处理和在用户空间中实现文件系统)卸载。具体而言,eBPF允许应用程序完全绕过I/O的POSIX抽象,并在用户空间中实现它们。eBPF补充了现有的内核绕过方法,如DPDK和SPDK,它们使得应用程序可以绕过内核进行网络和存储I/O。
超越机器抽象
POSIX提供了一种可移植地编写应用程序的抽象方式,可在类Unix操作系统变体和机器架构上运行。然而,当代应用程序很少在单个机器上运行。它们越来越多地使用远程过程调用(RPC)、HTTP和REST API、分布式KV存储和数据库,所有这些都是使用高级语言(如JavaScript或Python)实现的,运行在托管的运行时上。这些托管的运行时和框架暴露了隐藏其底层POSIX抽象和接口的接口。此外,它们还允许应用程序使用C之外的编程语言进行编写,而C是Unix和POSIX的编程语言。因此,对于许多当代系统和服务的开发者来说,POSIX在很大程度上已经过时,因为它的抽象是低级的,并且与单个机器绑定在一起。
然而,云和无服务器平台现在面临的问题与之前的POSIX操作系统相似:它们的API是分散且特定于平台的,这使得编写可移植的应用程序变得困难。此外,这些API仍然是以CPU为中心的,这使得在不使用定制解决方案的情况下,难以高效地利用特殊用途的加速器和非集成硬件。例如,可以认为JavaScript今天与过去的POSIX处于类似的位置:它将应用程序逻辑与底层操作系统和机器架构解耦。然而,JavaScript运行时仍然是以CPU为中心的,这使得将JavaScript应用程序的某些部分卸载到运行在NIC或存储设备上的加速器变得困难。具体而言,我们需要一种能够表达应用程序逻辑的语言,使得编译器和语言运行时能够高效地利用不同硬件堆栈中新兴的大量硬件资源的能力。与此同时,思考一下如果POSIX中没有以CPU为中心的特点,这些设备的硬件设计会有多么不同,将是一个有趣的思想实验。
结束语
多年来,POSIX已经成为操作系统抽象和接口的标准。抽象设计的两个驱动因素是硬件约束和当时的应用场景。今天,I/O和计算之间的速度平衡正在向I/O倾斜,这在一定程度上解释了为什么协处理器和特殊用途的加速器越来越受欢迎。因此,我们认为POSIX时代已经结束,未来的设计需要超越POSIX,并在更高的级别上重新思考抽象和接口。我们还认为操作系统接口必须改变以支持这些更高级别的抽象。
原文地址:超越POSIX:一个时代的终结?
相关文章:

超越POSIX:一个时代的终结?
在本文中,我们通过对Portable Operating System Interface(POSIX)抽象的历史演变进行系统性的回顾,提供了一个全面的视图。我们讨论了推动这些演变的一些关键因素,并确定了在构建现代应用程序时使它们不可行的缺陷。 …...
秋招算法备战第22天 | 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode) 在一个二叉搜索树中,两个节点 p 和 q 的最近公共祖先可以通过以下的算法找到: 从根节点开始。如果当前节点的值大于 p 和 q 的值,那么你需要转向左子树。因为在二叉…...

小程序之移花宫-自定义底部标签图标---【浅入深出系列005】
浅入深出系列总目录在000集 如何0元学微信小程序–【浅入深出系列000】 不会导入/打开小程序的看这里 让别人的小程序长成自己的样子-更换window上下颜色–【浅入深出系列001】 文章目录 本系列校训学习资源的选择 学习目标图标的注意事项图标资源打开小程序动手实践找到图标最…...

题目1 SQL注入(保姆级教程)
url:http://192.168.154.253:81/ #打开http://XXX:81/,XXX为靶机的ip地址 审题 1、打开题目看到有一个提示,此题目需要通过SQL注入漏洞读取/tmp/360/key文件,key在这个文件中 2、开始答题 发现这里url中有一个id的参数࿰…...

PDF转换成word乱码了怎么办?最实用的方法在这里!
在日常办公中,我们常常需要将PDF文件转换成Word文件,以便于编辑和修改。然而有时候在PDF转Word的过程中可能会遇到乱码的问题,让人感到困扰。在面对这种情况时,我们需要选择正确的方法,避免文件转换后出现乱码。下面我…...

字节跳动后端面试,笔试部分
var code "7022f444-ded0-477c-9afe-26812ca8e7cb" 背景 笔者在刷B站的时候,看到了一个关于面试的实录,前半段是八股文,后半段是笔试部分,感觉笔试部分的题目还是挺有意思的,特此记录一下。 笔试部分 问…...

[JavaScript游戏开发] 2D二维地图绘制、人物移动、障碍检测
系列文章目录 第一章 2D二维地图绘制、人物移动、障碍检测 第二章 跟随人物二维动态地图绘制、自动寻径、小地图显示(人物红点显示) 文章目录 系列文章目录前言一、列计划1.1、目标1.2、步骤 二、使用步骤2.1、准备素材(图片):草坪、人物(熊猫)、障碍(石头)2.2、初…...

区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型
区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型 目录 区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于QRF随机森林分位数回归时间序列区间预测模型࿱…...

.NET网络编程——TCP通信
一、网络编程的基本概念 : 1. 网络 就是将不同区域的电脑连接到一起,组成局域网、城域网或广域网。把分部在不同地理区域的计算机于专门的外部设备用通信线路 互联成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,…...

【Python机器学习】实验01 Numpy以及可视化回顾
文章目录 一、Numpy的基础知识实验1 生成由随机数组成的三通道图片,分别显示每个维度图片,并将三个通道的像素四周进行填充,分别从上下左右各填充若干数据。 二、Numpy的线性代数运算实验2 请准备一张图片,按照上面的过程进行矩阵…...

vue3-组件中的变化
1. 路由 1. 安装指令:npm i vue-routernext 2. 创建路由:createRouter2. 异步组件(defineAsyncComponent) defineAsyncComponent 是用于定义异步组件的函数。defineAsyncComponent 接受一个工厂函数作为参数,这个工厂…...
认识主被动无人机遥感数据、预处理无人机遥感数据、定量估算农林植被关键性状、期刊论文插图精细制作与Appdesigner应用开发
目录 第一章、认识主被动无人机遥感数据 第二章、预处理无人机遥感数据 第三章、定量估算农林植被关键性状 第四章、期刊论文插图精细制作与Appdesigner应用开发 更多推荐 遥感技术作为一种空间大数据手段,能够从多时、多维、多地等角度,获取大量的…...
数学建模的六个步骤
一、模型准备 了解问题的实际背景,明确其实际意义,掌握对象的各种信息,以数学思路来解释问题的精髓,数学思路贯彻问题的全过程,进而用数学语言来描述问题。要求符合数学理论,符合数学习惯,清晰…...

【计算机组成原理】24王道考研笔记——第二章 数据的表示和运算
第二章 数据的表示和运算 一、数值与编码 1.1 进制转换 任意进制->十进制: 二进制<->八进制、十六进制: 各种进制的常见书写方式: 十进制->任意进制:(用拼凑法最快) 真值:符合人…...

JQ-6 Bootstrap入门到实战;Bootstrap的(优缺点、安装、响应式容器原理、网格系统、响应式工具类、Bootstrap组件);小项目实践
目录 1_认识Bootstrap1.1_概念1.2_起源和历史1.3_Bootstrap优缺点 2_Bootstrap4的安装2.1_方式一 CDN2.2_方式二 : 下载源码引入2.3_方式三 : npm安装 3_Bootstrap初体验4_响应式容器原理4.1_屏幕尺寸的分割点(Breakpoints)4.2_响应式容器Containers 5_网…...

如何用3D格式转换工具HOOPS Exchange读取颜色和材料信息?
作为应用程序开发人员,非常希望导入部件的图形表示与它们在创作软件中的外观尽可能接近。外观可以在每个B-Rep面的基础上指定,而且,通过装配层次结构的特定路径可以在视觉外观上赋予父/子覆盖。HOOPS ExchangeHOOPS Exchange可捕获有关来自各…...
[Ubuntu 22.04] 安装docker,并设置镜像加速
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; doneapt install -y curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates# 添加Docker的GPG公钥和apt源 #curl -sSL https://download.d…...

如何使用GPT作为SQL查询引擎的自然语言
生成的AI输出并不总是可靠的,但是下面我会讲述如何改进你的代码和查询的方法,以及防止发送敏感数据的方法。与大多数生成式AI一样,OpenAI的API的结果仍然不完美,这意味着我们不能完全信任它们。幸运的是,现在我们可以…...
Servlet3.0上传文件
页面: <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>文件上传</title> </head> <body> <form action"fileup" enctype"multipart/form-data" method"…...
【ARM Cache 系列文章 6 番外篇 – MMU, MPU, SMMU, PMU 差异与关系】
文章目录 MMU 与 MPU 之间的关系MMU 与 SMMU 之间的关系MMU 与 PMU 之间的关系 上篇文章:ARM Cache 系列文章 5 – 内存屏障ISB/DSB/DMB MMU 与 MPU 之间的关系 MMU(Memory Management Unit)和MPU(Memory Protection Unit&#…...

NetSuite ERP顾问的进阶之路
目录 1.修养篇 1.1“道”是什么?“器”是什么? 1.2 读书这件事儿 1.3 十年计划的力量 1.3.1 一日三省 1.3.2 顾问损益表 1.3.3 阶段课题 2.行为篇 2.1协作 2.2交流 2.3文档管理 2.4时间管理 3.成长篇 3.1概念能力 3.1.1顾问的知识结构 …...

js 新浏览器打开页面
博主gzh:“程序员野区”,回复“加群”,可进博主web前端微信群 效果如下 setTimeout(()>{var url "https://blog.csdn.net/xuelang532777032?typeblog"; //要打开的网页地址var features "height500, width800, top100, left100, …...

jmeter软件测试实验(附源码以及配置)
jmeter介绍 JMeter是一个开源的性能测试工具,由Apache软件基金会开发和维护。它主要用于对Web应用程序、Web服务、数据库和其他类型的服务进行性能测试。JMeter最初是为测试Web应用程序而设计的,但现在已经扩展到支持更广泛的应用场景。 JMeter 可对服务…...

ZooKeeper原理剖析
1.ZooKeeper简介 ZooKeeper是一个分布式、高可用性的协调服务。在大数据产品中主要提供两个功能: 帮助系统避免单点故障,建立可靠的应用程序。提供分布式协作服务和维护配置信息。 2.ZooKeeper结构 ZooKeeper集群中的节点分为三种角色:Le…...

【算组合数】CF1833 F
少见地秒了这道1700,要是以后都这样就好了.... Problem - F - Codeforces 题意: 给定一个数列,让你在这个数列里找一个大小为M的子集,使得极差不超过M 思路: 子集,不是子序列,说明和顺序无…...

Attention详解(自用)
encoder-decoder 分心模型:没有引入注意力的模型在输入句子比较短的时候问题不大,但是如果输入句子比较长,此时所有语义完全通过一个中间语义向量来表示,单词自身的信息已经消失,可想而知会丢失很多细节信息࿰…...
pptx转pdf工具类
引入依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.0.0</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxm…...

2023华为OD统一考试(B卷)题库清单(持续收录中)以及考点说明
目录 专栏导读2023 B卷 “新加题”(100分值)2023Q2 100分2023Q2 200分2023Q1 100分2023Q1 200分2022Q4 100分2022Q4 200分牛客练习题 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷)》。 刷的越多&…...

论文笔记--Won’t Get Fooled Again: Answering Questions with False Premises
论文笔记--Won’t Get Fooled Again: Answering Questions with False Premises 1. 文章简介2. 文章概括3 文章重点技术3.1 大模型面对FPQs的表现3.2 False QAs数据集3.3 训练和评估 4. 文章亮点5. 原文传送门 1. 文章简介 标题:Won’t Get Fooled Again: Answerin…...
【Django】include app_name和namespace的区别
app_name 区分不同app的url的name,防止不同app之间,url_name的重名,引用时加入app_name:name namespace 区分不同路由 include同一个view module的情况, 让不同路由进入同一个view中,进行reverse时,根据对…...