DAOS学习笔记及思考

DAOS带来的思考

根据daos docs的描述,DAOS是Intel基于NVMe全新设计开发并开源的异步对象存储,充分利用下一代NVMe技术的优势,对外提供KV存储接口,提供非阻塞事物I/O,端到端完整性,细粒度的数据控制,数据保护以及弹性存储等特征。

intel daos给我们提供了基于NVMe实现高性能存储引擎的参考实现核心是并行性,如何发挥多核CPU及NVMe设备提供的并行能力

以大家熟悉的Ceph,BeeGFS为例,对并行不足及超额订购问题进行说明:

  1. Ceph的每个OSD管理一块SSD,为提升并发能力每个OSD内部会划分多个Shard,Shard内I/O串行执行,Shard间I/O可并发,PG通过模Shard数映射到Shard,接收到的I/O请求根据pg_id取模放入指定的Shard,由Shard内的工作线程调度执行。I/O提交到引擎后,通过单线程libaio(批)提交到设备(独立的KV线程提交元数据I/O,元数据提交后再归还工作线程)。

Ceph OSD通过Shard来控制并发,以粗粒度的PG为并发单位,限制了PG及PG内对象I/O的并发能力,导致系统的并行性不足;理论上可以尽可能的增加PG及OSD Shard的数量(及工作线程数量),以此来提升系统的并发能力,但这会带来严重的线程上下文切换开销,大量的CPU时间被浪费在内核中,导致CPU超额订购问题。

  1. BeeGFS的每个OSD管理一块SSD,采用Multi-reactor的网络模式,从线程池给每个客户端连接分配一个工作线程用于处理I/O。I/O提交到引擎后,通过POSIX接口(pread/pwrite, read/write)提交到设备,I/O完成后再归还工作线程。

BeeGFS通过从线程池分配一个工作线程来处理每个客户端连接的I/O,工作线程采用同步操作来处理I/O,因此线程会被阻塞直到I/O完成,这严重影响了系统的并行性;SSD的性能很高,需要很多的并发操作才能充分发挥其性能,因此也可以往线程池中添加足够多的工作线程,以此来提升系统的并发能力,但这会带来严重的线程上下文切换开销,大量的CPU时间被浪费在内核中,导致CPU超额订购问题。

daos是如何解决上述问题的呢?,概括起来就两点:轻量线程和非阻塞I/O。下图是我结合dao docs以及daos 代码,绘制的一张daos 并行设计图:
Daos Engine并行设计图
轻量线程:在双路x86系统上,一个DAOS节点(DAOS Server)通常包含两个存储引擎(DAOS Engine),每个引擎绑定一个Socket,管理多个NVMe SSD。为了避免超额订购,daos引擎使用了用户态轻量线程框架-argobots,不仅减少了上下文切换的开销,也实现了在没有内核干预下的完全调度控制。如上图,daos_engine引擎启动时,启动若干执行单元(XS)并绑定到独立的cpu core。每个XS内运行一个自定义的调度器(Scheduler),负责根据策略执行三个线程池(pools)中的轻量线程(协程),进而执行用户任务。从功能角色上,XS分成3类:系统XS,负责处理系统管理任务,如:swim心跳,dRPC请求,dmg请求等;主XS,负责处理客户端I/O;辅助XS,协助主XS进行计算密集型任务,如:加密,压缩,重建等。daos引擎在运行时根据类型将用户任务添加到各XS的各线程池,每类XS有若干,其中每个主XS负责一个Target的I/O处理,Target是逻辑设备,一个Target和NVMe SSD设备的一个IO Channel(QP)绑定,通过多个主XS,多个Targets和多个IO Channel(QP)的绑定,实现NMVe SSD设备的多队列并发能力。

非阻塞I/O:Linux系统提供了多种存储I/O接口,包括:posix接口,libaio,io_uring以及spdk。posix接口是linux上使用最普遍的I/O接口,通过posix接口发起文件系统I/O后,调用线程会被阻塞知道I/O完成。libaio是异步I/O接口,允许一次提交多个I/O请求,减少用户态和内核态切换的开销。io_uring是Linux中新引入的异步I/O接口,用于替代libaio,它通过mmap共享内存在用户态和内核态直接交换数据,允许一次提交多个I/O请求,支持Polling模式,减少中断带来的延迟及CPU开销。spdk是intel实现的存储性能开发套件,它实现了用户态的NVMe驱动,与其他的I/O接口不同,spdk直接在用户态分配QP,提交请求到内存的ring buffer,接着更新标志通知SSD有新的请求到来。关于几种I/O的对比,在2022 SYSTOR上发的一篇论文UnderStanding Modern Storage APIs有详细的分析,daos中使用的是spdk。

DAOS服务端启动流程

下面这张图摘自daos internals,很好的说明了daos server内部的服务分层及其(和模块)的交互关系
DAOS Server内部分层图
如上图,daos服务端包括控制平面和数据平面两个平面,daos的控制面是非中心化的全分布式设计和数据面部署在相同的节点,两者通过dRPC通信(Unix Socket),这点与其他开源的分布式存储系统不同,如:glusterfs,ceph,beegfs等。daos控制服务(daos_server)负责daos数据服务(daos_engine)的管理和资源的供给,如:网络、存储的供给,数据服务的安装、启动等。各daos_server服务承担的角色并不完全对等,(根据配置)其中有部分服务会启动raft一致性协议,负责集群拓扑、节点状态的持久化。下图是我绘制的daos_server和daos_engine启动过程中的交互时序:4节点集群,配置了3个Raft节点,各节点上的daos_server负责拉起本地的daos_engine(在常见的两路x86服务器上,每个socket上会启动一个daos_engine,图中只画了一个)
daos_server和daos_engine启动交互

  1. 执行systemctl start daos_server启动daos_server过程中,启动daos_engine
  2. daos_engine启动后,向daos_server发送ready的dRPC通知,然后等待daos_server的SetUp消息更新init_state
  3. 各daos_server向MS Leader发起JoinSys的gRPC消息,MS Leader将daos_engine加入集群(db),置位needUpdateGroup标志
  4. 各daos_server向daos_engine发起SetRank的dRPC消息,daos_engine更新Cart group中的membs和swim membs以及缓存uri
  5. 各daos_server向daos_engine发起SetUp的dRPC消息,daos_engine设置init_state状态为DSS_INIT_STATE_SET_UP【daos_engine得以继续执行,接着会完整各模块的SetUp,最后激活utl barrier信号量,启动所有的xs,这样就可以提供服务了】
  6. MS Leader在检查到needUpdateGroup标志后,向daos_engine发起GroupUpdate的dRPC消息(任意一个daos_engine发送成功即可),daos_engine更新Cart group中的membs和swim membs以及缓存uri。【MS Leader所在节点上的daos_engine学习到其他daos_engine的存在】
  7. MS Leader节点上的daos_engine启动ULT线程(如果未启动),向其他daos_engine发送MAP_UPDATE的gRPC消息,广播membs及状态信息给其他daos_engine。【各daos_engine学习到其他daos_engine的存在】
  8. 各daos_engine通过SWIM Gossip获取,更新相互间的状态(swim xs调用注册的回调,直接或间接ping swim membs中其他daos_engine),监测到dead engine就通过注册的网络事件回调向daos_server发送RAS_TYPE_STATE_CHANGE的RAS dRPC消息
  9. 收到RAS dRPC消息的daos_server向MS Leader转发RAS消息,发起ClusterEvent类型的gRPC消息,MS Leader更新engine的状态到db,置位needUpdateGroup标志【会激活过程6,正是通过上述的过程6-9,daos系统实现了engine状态的管理】

注:上述的过程1-9,隐藏了三个daos_server的raft选主。daos系统的集群信息由选出的raft leader负责更新,并通过raft 日志复制在三个节点间实现集群配置的一致性和可靠性。

执行完上面的启动过程,一套新的daos系统就准备就绪了,下文是服务启动过程中核心的代码调用过程说明,代码基于v2.4版本,比较繁琐无趣,对代码感兴趣的读者可以了解下,希望对你走读代码有帮助。

Intel DAOS异步对象存储的实现涉及硬件、操作系统及KV等方面的知识,其内部集成了很多的第三方库,在研究其代码前,建议各位读者:

  1. 认真阅读daos docs,掌握各种概念,设计原理,代码结构,安装配置方法等
  2. 了解各第三方库的工作原理,结合examples掌握其使用方法,如:raft,argobots,cart(mercury),spdk,pmdk等
  3. 认真阅读代码中各模块的README文件,如:rsvc,rdb,vos,pool,container,object,mgmt,dtx
  4. 准备一套测试环境,结合运行Log,加深对代码细节的理解

DAOS Server的核心启动过程

DAOS Server是控制面服务,通过systemctl start daos_server启动服务后,会执行/usr/bin/daos_server start命令,最终调用src/control/server/server.go中的Start方法,核心过程如下:

server.Start //环境检查及初始化,初始化server实例,初始化raft,control服务,ms服务,初始化网络,实例化Engine,实例化grpc,启动raft,注册raft回调newServer //初始化server实例createServices //初始化raft,control服务,ms服务initNetwork //初始化网络,创建grpc监听addEngines //发起BdevPrepareRequest请求准备nvme设备,实例化Engine,注册onAwaitFormat,onStorageReady,onReady等回调//实例化grpc,注册control,ms服务,启动raft//MS Leader会在raft回调中启动Loop,负责groupupdate的消息处理-将当前的Engines(Ranks)通过drpc发送给其中的一个Engine//Egnine收到消息后,更新CART group中的membs列表,启动rsvc mgmt服务,启动广播ULT线程-发送MAP_UPDATE的grpc消息,广播membs给其他Engine,收到消息的Engine会更新membs,执行通知回调crt_plugin_gdata.cpg_event_cbs,这样就和SWIM关联起来了setupGrpc server::registerEvents //注册RAS事件,注册raft回调server::start  //启动server:启动gRPC,启动dRPC,启动MS的异步Loop-处理PoolCreate、Join、PoolEvict消息,启动EngineEngineHarness::Start  //逐个启动EngineInstance,安装newOnDrpcFailureFn回调【如果是MS Leader,该回调在dRPC处理失败会触发并发起MS重新选主】EngineInstance::RunEngineInstance::startRunnerEngineInstance::format EngineInstance::awaitStorageReady //格式化(检查)SCM,回调onAwaitFormat【记录一个NoticeInfo的Log】EngineInstance::createSuperblock //挂载SCM,初始化Superblock并持久化到Superblock文件EngineInstance::onStorageReady //执行回调onStorageReady【发起BdevPrepareRequest请求清理大页,更新cfg mem_size,检查tmpfs的内存】EngineInstance::start  Runner::Start //根据配置文件和环境变量,初始化启动命令行Runner::Runner //启动Engine,在协成中安装退出channel,信号处理器等EngineInstance::waitReady //等待来自Engine的dRPC ready通知EngineInstance::finishStartup //更新Superblock,发起RPC加入系统,发起SetRank和SetUp dRPC请求,执行OnReady回调EngineInstance::handleReadyEngineInstance::updateFaultDomainInSuperblock //更新Superblock中的FaultDomain故障域信息并持久化到Superblock文件EngineInstance::determineRank //向MS Replica发起RPC Join请求-Instance加入系统,持久化到membership db,分配Rank,置位MS Leader的groupupdate标志,返回后更新Superblock并持久化到Superblock文件//对于非MS Leader节点(Leader会在上面的join请求中直接发起SetupRank的dRPC请求),向Engine发起SetRank和SetUp dRPC请求,接着设置ready标志(MS Leader根据该标志进行一次groupupdate消息处理)//收到SetRank dRPC消息,Engine会更新Cart group中的mems列表和 swim membs列表,缓存uri//收到SetUp dRPC消息,Engine会更新init state,至此,Engine服务就完全run起来了EngineInstance::SetupRank  EngineInstance::onReady  //执行回调onReady【置位allStarted标志,执行Server的onEnginesStarted回调-启动Prometheus exporter】

DAOS Engine的核心启动过程

daos server负责daos engine的管理,包括:启停,成员状态管理等,它们直接通过dRPC(Unix socket)通信。在daos server启动过程中,会根据配置文件及环境变量构建参数启动daos engine,执行的命令是:/usr/bin/daos_engine --args...,调用的是:src/engine/init.c中的main方法

main  //初始化选项,启动engine,等待退出parse //根据命令行参数初始化选项server_init //启动hlc_recovery_begin //开始HLC时钟恢复dss_topo_init //初始化CPU topology信息,这里会设置socket的core map以及engine上的目标target数,最佳的core数:2+helpers+targetsregister_dbtree_classes //注册各种btree class到全局数组btr_class_registeredabt_init //初始化argobots任务框架,daos使用argobots来进行任务调度crt_init_opt //初始化cart网络框架:初始化全局的cart结构,根据配置初始化primary和secondary provider,初始化primary和secondary的group信息,NA配置,及其他一些结构daos_hhash_init //初始化全局handle hash表pl_init //初始化全局placement hash表ds_iv_init //初始化incast variable树modules_load //加载各module,各模块保存在全局列表中,hlc_recovery_end  //停止HLC时钟恢复dss_set_start_epoch() //初始化初始化epoch:dss_start_epochbio_nvme_init //根据配置初始化nvme全局结构,初始化spdk环境//初始化各模块:调用模块的init接口初始化模块,(如果有key)添加模块到全局数组dss_module_keys,添加gRPC handler到cart的opc_map, 添加dRPC handler到全局register_table//vos:注册container,dtx,object的btree结构到全局数组btr_class_registered;添加模块到全局数组dss_module_keys//rdb:初始化rdb_hash表//rsvc:初始化rsvc_hash表,用来暂存已open的rsvc服务,如:rsvc_pool//pool:初始化pool lru cache,初始化pool handle hash表,注册pool的各incast variable类到ds_iv_class_list列表,初始化pool的默认ACL属性,注册rsvc_pool类到rsvc_classes数组,初始化nvme的reaction ops;添加模块到全局数组dss_module_keys//container:初始化container lru cache,初始化container handle hash表;添加模块到全局数组dss_module_keys//object:注册btree class到全局数组btr_class_registered,注册各副本类和EC类到全局数组oc_ident_array,注册EC类到全局数组ecc_array;添加模块到全局数组dss_module_keys//mgmt:设置id,注册rsvc_mgmt类到rsvc_classes数组//dtx:根据环境变量初始化选项,注册btree class到全局数组btr_class_registered;添加模块到全局数组dss_module_keys//securty:初始化socket路径//rebuild:初始化全局结构rebuild_gst,注册rebuild的各incast variable类到ds_iv_class_list列表;添加模块到全局数组dss_module_keysdss_module_init_all dss_srv_init //初始化全局xs结构:xstream_data,初始化全局tls,初始化系统db,启动各xs,启动dRPC监听vos_standalone_tls_init //初始化全局tls:self_mode.self_tlsdss_sys_db_init  //初始化全局系统db,打开系统pool及containerbio_register_bulk_ops //注册公共的bulk分配及释放方法//逐个启动xs:system xs + main xs + helper xs,xs是argobots中的概念,类比硬件执行单元,可以将xs看成是其软件实现,通常和硬件执行单元一对一映射,如果将xs绑定到特定的core上//system xs,包括:sys_xs负责系统任务,独占一个core,swim_xs负责保活心跳, drpc_xs负责drpc请求,swim_xs和drpc_xs共享一个core//main xs:每个target一个 main xs,target是daos里面的逻辑设备抽象,与spdk中的io_channel(nvme qp)对应,用于提高并行性;每个main xs独占一个core//helper xs:用于协助target处理加密,压缩等高CPU任务dss_xstreams_init dss_start_xs_id  //分配 cpu coredss_start_one_xstreamdss_xstream_alloc //创建xs实例dss_sched_init //创建自定义argobots sheduler,设置任务池pool来区分任务优先级(网络,nvme,通用三个池),添加到argobots框架的执行单元(ULT和tasklet)根据该scheduler定义的策略调度ABT_xstream_create_with_rank //创建xs,并设置上述的schedulerdaos_abt_thread_create //创建xs的主ULT:dss_srv_handler,添加到网络池(调度执行)ABT_cond_wait //等待信号量,直到上面的主ULT被调度执行bio_nvme_ctl //设置全局nvme bdev启动状态为:BIO_CTL_NOTIFY_STARTED,使得后文xs中spdk subsystem初始化及创建的nvme的ULT可以继续执行drpc_listener_init //在 dRPC xs中创建ULT线程启动dRPC监听drpc_notify_ready //向daos_server发起ready就绪通知,daos_server会向MS Leader发送JoinSys的gRPC消息,向daos_engine回发SetRank和SetUp的dRPC消息server_init_state_wait //等待来自daos_server的init_state更新:收到daos_server的SetUp消息后会设置init_state状态为DSS_INIT_STATE_SET_UP//pool:在system xs创建ULT逐个启动各pool,启动的pool服务添加到rsvc_hash表//mgmt:创建ULT清理僵尸pool(如果有),清理未完成pool(如果有),初始化pooltgts结构用于跟踪创建过程中的pool//dtx:给各main xs创建事务批提交ULT:dtx_batched_commit,聚合ULT:dtx_aggregation_maindss_module_setup_all //安装各模块:调用各模块的setup接口安装模块crt_register_event_cb //注册网络事件回调dss_crt_event_cb,如:groupupdate或者swim状态更新crt_register_hlc_error_cb //注册HLC错误回调dss_crt_hlc_error_cbdss_xstreams_open_barrier //激活utl barrier信号量,启动所有的xs// xs的主线程ULTdss_srv_handlerdss_xstream_set_affinity //绑核dss_tls_init //初始化tls,与该xs相关的信息会存储在tls中	crt_context_create //(如果需要)初始化Cart网络上下文,sys_xs,swim_xs,main_xs以及每个main_xs的第一个helper_xs会起用网络crt_context_initcrt_hg_ctx_init //根据配置的网络provider初始化HG(mercury),注册HG rpc handled_tm_add_metric //添加metric指标crt_swim_init //如果是swim_xs,初始化swim上下文,注册swim回调crt_swim_progress_cb,注册rpc handler到opc_mapcrt_context_register_rpc_task //注册rpc句柄dss_rpc_hdlr和dss_iv_resp_hdlr:io请求首先由上述注册的HG rpc handle响应,然后转发给这里注册的rpc handle做进一步的调度处理,最终调用op code的处理函数tse_sched_init //初始化任务调度器bio_xsctxt_alloc //(如果需要)通常只有main xs才会使用nvme,但是如果开启了metadata-on-ssd,sys_xs也会;第一个xs(main_xs或者sys_xs)会根据配置文件初始化所有的spdk subsystem,创建blobstore,将初始化的bio_bdev设备挂接到nvme_glb全局列表中。给target选择合适的nvme设备(targets循环绑定到已有target数最少的nvme上,dev和targets信息持久化到db中),并创建io_channel daos_abt_thread_create //创建ULT添加到nvme池,等待argobots调度执行:负责nvme设备的状态监测,设备的热插拔监测等ABT_cond_signal //激活信号量,以便调用线程能继续运行ABT_cond_wait //如果是swim_xs则立即开始后面的循环,如果是非swim xs,等收到daos_server的dRPC消息setUp后再执行for (;;)  //主ULT循环,如果该xs开启了Cart网络,会调用HG(mercury)接口推进rpc的调用及回调处理(swim xs会执行上述注册的crt_swim_progress_cb进行engine状态探测)wait_all_exited //等待所有ULT退出,engine退出

参考资料

Argobots论文
高性能I/O引擎论文

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/117158.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity的Camera类——视觉掌控与深度解析(上)

前言 摄像机在任何3D场景中都是至关重要的元素,尤其是在游戏和实时应用中。它定义了玩家和用户如何“看到”虚拟世界。Unity中的Camera类提供了一系列强大的工具,让开发者可以精细地控制渲染和视图。在本文中,我们将深入探索这个核心类的使用…

【Java】小计 TCP UDP的区别

面向连接 TCP面向连接,需要连接,而UDP不需要建立连接 可靠性 TCP协议通过确认应答、连接管理、流量控制、拥塞控制来确保可靠性传输;UDP不保证可靠性传输。 性能 TCP传输效率慢,需要较多的资源开销,UDP传输效率快&am…

某马机房预约系统 C++项目(二) 完结

8.4、查看机房 8.4.1、添加机房信息 根据案例&#xff0c;我们还是先在computerRoom.txt中直接添加点数据 //几机房 机器数量 1 20 2 50 3 1008.4.2、机房类创建 ​ 同样我们在头文件下新建一个computerRoom.h文件 添加如下代码&#xff1a; #pragma once #include<i…

pnp单目相机标定测距

参考&#xff1a;opencv 单目相机pnp测距&#xff08;Cpp&#xff09;-CSDN博客

【python】文件和异常

文件和异常 实际开发中常常会遇到对数据进行持久化操作的场景&#xff0c;而实现数据持久化最直接简单的方式就是将数据保存到文件中。说到“文件”这个词&#xff0c;可能需要先科普一下关于文件系统的知识&#xff0c;但是这里我们并不浪费笔墨介绍这个概念&#xff0c;请大…

凉鞋的 Godot 笔记 204. 语句

204. 语句 在上一篇&#xff0c;我们接触了三种常见的类型&#xff0c;如下所示&#xff1a; 这样我们算是对变量进行了一个入门了。 其实我们除了变量&#xff0c;我们还接触了一个叫做语句的概念。 我们可以看下代码: extends Node# Called when the node enters the sce…

IDEA配置HTML和Thymeleaf热部署开发

IDEA配置HTML和Thymeleaf热部署开发 1.项目配置2. IDEA配置3. 使用 需求&#xff1a;现在我们在开发不分离项目的时候&#xff08;SpringBootThmeleaf&#xff09;经常会改动了类或者静态html文件就需要重启一下服务器&#xff0c; 这样不仅时间开销很大&#xff0c;而且经常重…

PageHelper基础知识

使用场景 便用mybatis&#xff0c;可以用 pagehelper 分页 。 maven依赖 <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>4.1.6</version> </dependency>PageHelper配…

webpack配置css-loader让scss文件支持模块化引入

1. webpack部分: 重点: modules: true, // 为false引入就是空对象, 无法使用 const path require(path) const webpack require(webpack) const webpackCommonConf require(./webpack.common.js) const { smart } require(webpack-merge) const { srcPath, distPath } r…

@Value注解的原理

1.AutowiredAnnotationBeanPostProcessor是主要逻辑类&#xff0c;基本逻辑同Autowird 2.PropertySourcesPlaceholderConfigurer中会将StringValueResolver添加到beanFactory 3.外部配置文件properties会加载到ConfigurableEnvironment中&#xff0c;具体逻辑是通过Applicati…

vscode中如何将cmd设置为默认终端

vscode中如何将cmd设置为默认终端&#xff1f;下面本篇文章给大家介绍一下vscode中设置默认终端为cmdPowerShelWSL等的方法&#xff0c;希望对需要的朋友有所协助&#xff01; 一、快捷键&#xff08;CtrlShiftP打开命令面板&#xff0c;输入select选择“SelectDefaultProfil …

mdadm命令详解及实验过程

mdadm命令详解及实验过程 ⼀.概念 mdadm是multiple devices admin的简称&#xff0c;它是Linux下的⼀款标准的软件 RAID 管理⼯具&#xff0c;作者是Neil Brown ⼆.特点 mdadm能够诊断、监控和收集详细的阵列信息 mdadm是⼀个单独集成化的程序⽽不是⼀些分散程序的集合&#…

Jupyter使用技巧-环境篇

不同于其他IDE&#xff0c;有时会出现找不到文件路径&#xff0c;通常是因为当前工作目录&#xff08;working directory&#xff09;不同所导致的。Jupyter Notebook 会在启动时选择一个初始的工作目录&#xff0c;而这个目录可能与你运行 .py 文件时所在的目录不同。 import…

SpringMVC系列-5 消息转换器

背景 SpringMVC系列的第五篇介绍消息转换器&#xff0c;本文讨论的消息转换指代调用Controller接口后&#xff0c;对结果进行转换处理的过程。 内容包括介绍自定义消息转换器、SpringMVC常见的消息转换器、Spring消息转换器工作原理等三部分。 本文以 SpringMVC系列-2 HTTP请求…

PHP 预定义超全局变量 笔记/练习

预定义超全局数组变量 $_FILES 练习在最后 其他练习跟在每条笔记后 概述 预定义&#xff1a;预定义变量是 PHP 已定义&#xff0c;可以直接使用超全局&#xff1a;作用域是全局&#xff0c;可以在脚本的任何地方&#xff08;包括函数内部、外部&#xff09;都可以进行访问 常…

关于集群和分布式部署

EJB的RPC是同步调用可实现分布式计算&#xff0c;是SessionBean和EntityBean用的&#xff0c;而JMS是异步调用。RMI&#xff0c;和webservice也可以实现分布式计算。 举例说明&#xff0c;假设我们的系统有三个EJB组件&#xff1a;人事、财务、销售&#xff0c;都是开放远程接口…

EGF中多项式exp的组合意义

EGF中多项式exp的组合意义 EGF一般用来处理多重集的排列问题&#xff0c;在其上可以定义多项式的exp运算&#xff0c;在处理一类问题的时候有独特的作用 我们考虑将n个有标号的元素分为k个非空无序集合的方案数&#xff0c;记其EGF为 F k F_{k} Fk​,再考虑 f i f_i fi​表示…

【Segment Anything Model】八:修改SAM源码做分类任务

🍉 博主微信 cvxiayixiao 🍓 【Segment Anything Model】计算机视觉检测分割任务专栏。 链接 🍑 【公开数据集预处理】特别是医疗公开数据集的接受和预处理,提供代码讲解。链接 🍈 【opencv+图像处理】opencv代码库讲解,结合图像处理知识,不仅仅是调库。链接 文章目…

使用GoogleNet网络实现花朵分类

一.数据集准备 新建一个项目文件夹GoogleNet&#xff0c;并在里面建立data_set文件夹用来保存数据集&#xff0c;在data_set文件夹下创建新文件夹"flower_data"&#xff0c;点击链接下载花分类数据集https://storage.googleapis.com/download.tensorflow.org/exampl…

前端 CSS 经典:clip、clip-path

1. clip 1.1 clip: auto | inherit | rect auto&#xff1a;默认&#xff0c;不裁剪 inherit&#xff1a;继承父级 clip 属性 rect&#xff1a;规则四边形裁剪 1.2 clip: rect(top, right, bottom, left) 注意&#xff1a; 1.裁剪只对 fixed 和 absolute 的元素有效。 2.top&…