当前位置: 首页 > news >正文

pytorch 融合 fuse 学习笔记

目录

fuse_lora 作用是什么

fuse_modules源码解读


fuse_lora 作用是什么

  1. 在深度学习模型微调场景下(与 LoRA 相关)
    • 参数融合功能
      • 在使用 LoRA(Low - Rank Adaptation)对预训练模型进行微调后,fuse_lora函数的主要作用是将 LoRA 模块学到的参数和原始模型的参数进行融合。以自然语言处理中的 Transformer 架构模型为例,在微调阶段,LoRA 会在模型的某些关键层(如多头注意力层)添加低秩矩阵来调整模型参数。
      • 当调用fuse_lora函数时,它会根据预定义的规则将这些额外的 LoRA 参数融入到原始模型的权重中。例如,假设原始模型某一层的权重矩阵为,LoRA 模块对应的权重矩阵为(通过微调得到),fuse_lora函数可能会执行类似于的操作来更新原始权重,使得模型能够以融合后的参数进行推理,避免在推理过程中还需要单独处理 LoRA 模块。
    • 优化推理性能
      • 从性能角度来看,在模型推理阶段,不融合 LoRA 参数可能会导致额外的计算开销。因为每次进行前向传播计算时,都需要考虑原始模型参数和 LoRA 参数的交互。通过fuse_lora函数将参数融合后,推理过程可以直接使用融合后的单一参数集,减少了计算量。
      • 例如,在处理大规模文本生成任务时,融合后的模型能够更快地生成文本,因为它在推理时不需要频繁地在原始模型和 LoRA 模块之间切换计算。同时,也减少了内存占用,因为不需要同时存储原始模型和 LoRA 模块的参数,这对于在资源有限的设备(如移动设备或边缘计算设备)上进行模型部署非常重要。
  2. 如果是在其他自定义的代码库或特定应用场景下(非典型的 LoRA 关联情况)
    • 特定的数据或功能融合
      • fuse_lora函数可能被定义为将与 “lora” 相关的数据结构或功能与其他部分进行融合。例如,在一个包含多种通信协议(假设 “lora” 代表一种低功耗广域网通信协议)的物联网软件系统中,fuse_lora函数可能用于将 Lora 协议相关的数据接收、处理功能与系统的主数据处理模块进行融合。
      • 这可能涉及整合 Lora 设备发送的数据格式(如传感器数据)到系统通用的数据存储或分析模块中,使得系统能够统一处理来自不同通信源的数据,提高系统的整体性和数据处理效率。具体的融合方式和作用完全取决于函数在该特定应用场景中的定义和设计目的。

fuse_modules源码解读

转自:pytorch中fuse_modules_pytorch中的fuse函数是什么意思-CSDN博客

1. 官方代码
 

torch.ao.quantization.fuse_modules — PyTorch 2.5 documentation

2. fuse_modules源码解读
仅融合以下序列:

conv, bn
conv, bn, relu
conv, relu
linear, relu
bn, relu
网络中所有其他序列保持不变,对于上述序列,用融合的模块替换列表中的第一项,用identity替换其余模块。
fuse_modules
def fuse_modules(model, modules_to_fuse, inplace=False, fuser_func=fuse_known_modules, fuse_custom_config_dict=None):
1
model:要进行操作的模型名称
modules_to_fuse:要融合的模块名称的列表。如果只有一个要融合的模块列表,可以是一个字符串列表,如:[‘conv1’, ‘bn1’, ‘relu’]
inplace:bool类型参数,默认为false。融合发生在模型上,默认会返回一个新模型
fuser_func:接收模块列表并输出相同长度的融合模块列表的函数。例如,fuser_func([convModule, BNModule]) 返回 [ConvBNModule, nn.Identity()] 。 默认为 fuse_known_modules
fuse_custom_config_dict :自定义配置,默认为none
fuse_known_modules
将给定的模块列表mod_list中的一些常见模块进行融合,返回融合后的模块列表。融合后的模块可以有效地减少模型计算量和内存占用,从而提高模型的计算效率。

参数:mod_list:一个包含了一系列PyTorch模块对象的列表,这些模块可以是常见的卷积、线性、批归一化等模块。
is_qat:指定模型是否使用量化感知训练(true使用,false不使用)
additional_fuser_method_mapping:一个可选的字典,用于指定额外的融合方法。字典的key是要融合的模块类型,value是一个融合函数,它将被用于融合指定类型的模块。默认为None。

def fuse_known_modules(mod_list, is_qat, additional_fuser_method_mapping=None):r"""Returns a list of modules that fuses the operations specifiedin the input module list.Fuses only the following sequence of modules:conv, bnconv, bn, reluconv, relulinear, bnlinear, reluFor these sequences, the first element in the output module list performsthe fused operation. The rest of the elements are set to nn.Identity()"""types = tuple(type_before_parametrizations(m) for m in mod_list)fuser_method = get_fuser_method(types, additional_fuser_method_mapping)if fuser_method is None:raise NotImplementedError("Cannot fuse modules: {}".format(types))new_mod : List[Optional[nn.Module]] = [None] * len(mod_list)fused = fuser_method(is_qat, *mod_list)# NOTE: forward hooks not processed in the two following for loops will be lost after the fusion# Move pre forward hooks of the base module to resulting fused modulefor handle_id, pre_hook_fn in mod_list[0]._forward_pre_hooks.items():fused.register_forward_pre_hook(pre_hook_fn)del mod_list[0]._forward_pre_hooks[handle_id]# Move post forward hooks of the last module to resulting fused modulefor handle_id, hook_fn in mod_list[-1]._forward_hooks.items():fused.register_forward_hook(hook_fn)del mod_list[-1]._forward_hooks[handle_id]new_mod[0] = fusedfor i in range(1, len(mod_list)):identity = nn.Identity()identity.training = mod_list[0].trainingnew_mod[i] = identityreturn new_mod


'
运行运行
在融合前,首先获取mod_list中每个模块的类型,并将它们作为一个元组存储在types变量中。这个元组中的类型用于选择要使用的模块融合方法。在默认情况下,该函数支持一些特定的模块序列进行融合。如果输入模块序列不符合这些支持的模式,则函数会尝试使用 additional_fuser_method_mapping 中定义的自定义融合函数fuser_method。
融合方法fuser_method :使用get_fuser_method() 函数根据types来选择一个合适的融合函数。
– 在 get_fuser_method函数中调用了字典DEFAULT_OP_LIST_TO_FUSER_METHOD(定义了元组和融合函数之间的映射关系)。下面仅展示部分2d模块融合

DEFAULT_OP_LIST_TO_FUSER_METHOD: Dict[Tuple, Union[nn.Sequential, Callable]] = {(nn.Conv2d, nn.BatchNorm2d): fuse_conv_bn,(nn.Conv2d, nn.BatchNorm2d, nn.ReLU): fuse_conv_bn_relu,(nn.Conv2d, nn.ReLU): sequential_wrapper2(nni.ConvReLU2d),(nn.Linear, nn.BatchNorm1d): fuse_linear_bn,(nn.Linear, nn.ReLU): sequential_wrapper2(nni.LinearReLU),(nn.BatchNorm2d, nn.ReLU): sequential_wrapper2(nni.BNReLU2d),
}



如果在特定模块序列的additional_fuser_method_mapping中提供了自定义fuser函数,则将使用该函数来代替默认的fuser函数。如果找不到合适的fuser函数,该函数将引发NotImplementedError
定义new_mod :使用 [None] * len(mod_list)创建一个长度为len(mod_list)的列表,这个列表中,每个元素都是一个nn.Module类型的可选对象,初始值为None。
融合后的新模块fused:使用fuser_method调用对应的融合函数,如 fuse_conv_bn(is_qat, conv, bn)得到一个模块融合后的新的模块(ConvBn2d)。该模块包含了卷积层和BN层的参数,并将其组合成一个新的运算,该融合模块的名称默认为ConvBn2d、ConvBn1d或ConvBn3d。fuse_conv_bn函数在后面进行介绍。
融合后,第一个for循环遍历 mod_list列表中第一个模块(mod_list[0])的handle_id(前向预处理钩子函数的ID)和hook_fn(前向预处理钩子函数,在模块前向传递时会被自动调用,用于执行某些操作,如记录中间结果、打印日志等。)。
– 然后,将这些钩子函数注册到fused模块中,使其能够在后续计算中被调用。
– 接着,从mod_list[0]._forward_pre_hooks字典中删除这些钩子函数,避免这些钩子函数被重复调用。
第一个for循环的作用是将mod_list列表中第一个模块的前向预处理钩子函数从原始模块对象中转移到融合模块对象中,以确保在使用融合模块进行前向传递时,所有需要的操作都能够被执行。
第二个for循环将mod_list列表中最后一个模块的前向钩子函数注册到fused模块中,并从原始模块对象的钩子字典中删除这些钩子函数。
与前向预处理钩子函数不同,前向钩子函数是在模块的前向传递过程中执行的,通常用于在模块输出计算完成后执行某些操作,如统计模型输出分布、进行可视化等。
最后,将融合好的fused模块赋给前面定义的new_mod 列表的第一个元素,最后使用for循环补充identity()到new_mod列表,使其长度和原始模块长度一致。
fuse_conv_bn
将给定的conv和bn模块融合并返回融合后的模块。

在此函数中构建了一个fused_module_class_map字典,用于指定模块类型与对应的融合模块类型之间的映射关系。

如果其类型在fused_module_class_map字典中有对应的融合模块类型,则将这些模块融合为一个新的模块(ConvBn2d),如果没有对应的融合模块类型,则不对其进行融合处理。

def fuse_conv_bn(is_qat, conv, bn):assert(conv.training == bn.training),\"Conv and BN both must be in the same mode (train or eval)."fused_module_class_map = {nn.Conv1d: nni.ConvBn1d,nn.Conv2d: nni.ConvBn2d,nn.Conv3d: nni.ConvBn3d,}if is_qat:assert bn.num_features == conv.out_channels, 'Output channel of Conv2d must match num_features of BatchNorm2d'assert bn.affine, 'Only support fusing BatchNorm2d with affine set to True'assert bn.track_running_stats, 'Only support fusing BatchNorm2d with tracking_running_stats set to True'fused_module_class = fused_module_class_map.get((type(conv)), None)if fused_module_class is not None:return fused_module_class(conv, bn)else:raise NotImplementedError("Cannot fuse train modules: {}".format((conv, bn)))else:return nn.utils.fuse_conv_bn_eval(conv, bn)


'
运行运行
返回调用的 fuse_conv_bn_eval(conv, bn) 函数如下

返回一个新的融合模块,该模块包含了卷积层和BN层的参数,并将其组合成一个新的运算。

def fuse_conv_bn_eval(conv, bn, transpose=False):assert(not (conv.training or bn.training)), "Fusion only for eval!"fused_conv = copy.deepcopy(conv)fused_conv.weight, fused_conv.bias = \fuse_conv_bn_weights(fused_conv.weight, fused_conv.bias,bn.running_mean, bn.running_var, bn.eps, bn.weight, bn.bias, transpose)return fused_conv



'
运行运行
3. fuse_modules实际测试
3.1 modules_to_fuse参数的使用方法
1. 此参数的列表可以包含多个需要融合的组合,子模块列表也可以,使用方法一
方法一:

modules_to_fuse = [ [‘conv1’, ‘bn1’, ‘relu1’], [‘submodule.conv’, ‘submodule.relu’]]

融合ResNet18中layer1的conv和bn层如下:

print('\n Before fusion \n\n', r18_o.layer1)

r18_o.eval()

r18 = torch.quantization.fuse_modules(
    r18_o,
    [['conv1', 'bn1', 'relu'],
     ['layer1.0.conv1', 'layer1.0.bn1'], # , 'layer1.0.relu'],
     ['layer1.0.conv2', 'layer1.0.bn2'],
     ['layer1.1.conv1', 'layer1.1.bn1'], #, 'layer1.1.relu'],
     ['layer1.1.conv2', 'layer1.1.bn2']]
)
print('\n After fusion\n\n', r18.layer1)

结果:

ResNet18融合前:(仅显示ResNet18中layer1的网络结构)


ResNet18融合后

此融合只将Conv2d和BN层进行融合,从上面对比可以看到融合后的 (bn) 变成了 identity(),(conv) 中的Conv2d是原本Conv2d和BN融合的。

2. 如果要融合的module被Sequential封装了,可使用方法二
方法二:

torch.quantization.fuse_modules(m, [‘0’, ‘1’, ‘2’], inplace=True)

1. 使用方法二对ResNet18中模块进行融合操作,融合代码如下:

def fuse_model(self):
    for m in self.modules():
        if type(m) == BasicBlock:
            torch.quantization.fuse_modules(m, [['conv1', 'bn1', 'relu'], ['conv2', 'bn2']], inplace=True)

运行运行
此处代码是仿pytorch官方写MobileNetV2模块融合,这部分代码写在 class ResNet(nn.Module) 中,后面融合直接使用model.fuse_model(),得到的方法二融合ResNet18结果如下:

此处是分别对(conv2d、bn、relu)和(conv2d、bn)进行融合融合

2. 使用方法二对MobileNetv2中模块进行融合操作

def fuse_model(self):
    for m in self.modules():
        if type(m) == ConvBNReLU:
            torch.quantization.fuse_modacules(m, ['0', '1', '2'], inplace=True)
        if type(m) == InvertedResidual:
            for idx in range(len(m.conv)):
                if type(m.conv[idx]) == nn.Conv2d:
                    torch.quantization.fuse_modules(m.conv, [str(idx), str(idx + 1)], inplace=True)

运行运行
结果:

MobileNetv2融合前(下面结果展示的是第一个残差模块,因此没有第一个1x1的卷积)


MobileNetv2融合后

从此对比可以看到,融合前的conv2d、bn、relu融合成了ConvRelu2d(Conv2d,ReLU),这里面的Conv2d是融合前的Conv2d和BN融合的。

相关文章:

pytorch 融合 fuse 学习笔记

目录 fuse_lora 作用是什么 fuse_modules源码解读 fuse_lora 作用是什么 在深度学习模型微调场景下(与 LoRA 相关) 参数融合功能 在使用 LoRA(Low - Rank Adaptation)对预训练模型进行微调后,fuse_lora函数的主要作…...

在 Ubuntu 20.04 上使用 Lux 下载 Bilibili 视频的详细教程

在 Ubuntu 20.04 上使用 Lux 下载 Bilibili 视频的详细教程 在 Ubuntu 20.04 上使用 Lux 下载 Bilibili(哔哩哔哩)视频的完整和详细步骤如下,包括使用预编译二进制文件的安装方法: 1. 安装依赖 确保你的系统已安装 FFmpeg&…...

【eclipse】快捷键

【eclipse】快捷键 编辑导航重构调试复制其他快速生成 Eclipse 提供了丰富的快捷键来帮助开发者提高工作效率。 以下是一些常用的 Eclipse 快捷键,它们覆盖了编辑、导航、重构、调试等多个方面。 这些快捷键能够显著提升开发效率,尤其是在处理大型项目时…...

集成开发环境(IDE)的使用技巧插件配置

在开发过程中,集成开发环境(IDE)的使用技巧和插件配置对提高工作效率、优化代码质量和加速调试至关重要。 一、IDE使用技巧 1. 代码导航 跳转到定义(Go to Definition):快速跳转到函数、类或变量的定义位…...

【如何提升代码工程质量】code review篇

应该对于基本上所有软件相关的公司来说,都有committer机制,即代码写好之后会提交合并请求,待相关人员code review通过后再进行合入,所以code review就是代码合入代码仓库的最后一道关卡,对于代码质量的影响也是不容忽视…...

Qt 面试题学习13_2024-12-1

Qt 面试题 1、 QString与基本数据类型如何转换?2、常用数据结构3、进程之间的道信方式有哪些? 1、 QString与基本数据类型如何转换? 1、将QString转换为基本数据类型通过QString的各种转换函数,可以将QString转换为int、float、double等基本数据类型。 QStri…...

Hive 安装与架构详解

Hive 安装(基于 Ubuntu 系统) 为了学习 Hive 的相关操作,我们需要先安装 Hive,以下是基于 Ubuntu 系统安装 Hive 的步骤: 下载 Hive 我们将使用 hive-0.13.1-cdh5.3.2 版本,当然你可以根据需要下载最新的…...

前端入门指南:模块打包器是什么?模块打包器的工作原理与实践

前言 在前端开发的生态系统中,随着项目复杂度和规模的不断提升,代码管理和优化变得至关重要。模块化开发作为一种有效的代码组织方式,极大地提升了代码的可维护性和复用性。 然而,面对大量的模块和复杂的依赖关系,如…...

初识ProtoBuf以及环境搭建(Win和Ubuntu)

初始ProtoBuf 序列化和反序列化的概念 序列化:把对象转换为字节序列的过程 称为对象的序列化。 反序列化:把字节序列恢复为对象的过程 称为对象的反序列化。 什么情况下需要序列化和反序列化? 存储数据:当你想把的内存中的对象状…...

springboot366高校物品捐赠管理系统(论文+源码)_kaic

毕 业 设 计(论 文) 高校物品捐赠管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此&#xff…...

【Python网络爬虫笔记】5-(Request 带参数的get请求) 爬取豆瓣电影排行信息

目录 1.抓包工具查看网站信息2.代码实现3.运行结果 1.抓包工具查看网站信息 请求路径 url:https://movie.douban.com/typerank请求参数 页面往下拉,出现新的请求结果,参数start更新,每次刷新出20条新的电影数据 2.代码实现 # 使用网络爬…...

递归算法讲解(c基础)

递归的定义 递归是指在函数的定义中使用函数自身的方法。它是一种解决问题的策略,将一个大型复杂的问题逐步分解为规模更小的、与原问题相似的子问题来解决。当子问题的规模足够小,达到一个可以直接求解的基本情况(也称为终止条件&#xff09…...

AJAX一、axios使用,url组成(协议,域名,资源路径)查询参数和化简,错误处理,请求/响应报文,状态码,接口文档,

一、AJAX是什么 概念 &#xff1a; AJAX是一种与服务器&#xff08;后端&#xff09;通信的技术 二、请求库axios的基本用法 1导包 2使用 // 1. 发请求 axios({ url: 请求地址 }).then(res > { // 2.接收并使用数据 }) <body><p class"province"…...

QT6学习第六天 初识QML

QT6学习第六天 创建Qt Quick UI项目使用Qt Quick DesignerQML 语法基础导入语句 import对象 object 和属性 property布局注释表达式和属性绑定QML 编码约定 设置应用程序图标 创建Qt Quick UI项目 如果你有只测试QML相关内容快速显示界面的需求&#xff0c;这时可以创建Qt Qui…...

映射vim键位,基本功能键位表(未更完)

键位映射&#xff1a;建议使用jj代替esc,毕竟esc离手那么远 linux下修改方法是&#xff1a;vim /etc/vim/vimrc 在该文件尾添加inoremap jj <Esc>该方法可以同样可以用到其他键位映射上 i&#xff1a;表示这个映射是在插入模式&#xff08;insert mode&#xff09;下有效…...

Python学习笔记(5)Python的创建型设计模式

创建型设计模式&#xff08;Creational Design Patterns&#xff09;&#xff0c;主要关注对象的创建机制。这类模式可以使得系统更加独立于如何创建、组合和表示其对象。通过将这些职责分离出来&#xff0c;创建型设计模式有助于提高代码的灵活性和复用性。 本书的范例代码已经…...

qt QAnimationDriver详解

1、概述 QAnimationDriver是Qt框架中提供的一个类&#xff0c;它主要用于自定义动画帧的时间控制和更新。通过继承和实现QAnimationDriver&#xff0c;开发者可以精确控制动画的时间步长和更新逻辑&#xff0c;从而实现丰富和灵活的动画效果。QAnimationDriver与QAbstractAnim…...

零拷贝相关知识点(一)

前言 大家好&#xff0c;我是程序员田螺。 零拷贝是老生常谈的问题啦&#xff0c;大厂非常喜欢问。比如Kafka为什么快&#xff0c;RocketMQ为什么快等&#xff0c;都涉及到零拷贝知识点。最近技术讨论群几个伙伴分享了阿里、虾皮的面试真题&#xff0c;也都涉及到零拷贝。因此…...

STM32的CAN波特率计算

公式&#xff1a; CAN波特率 APB总线频率 / &#xff08;BRP分频器 1&#xff09;/ (SWJ BS1 BS2) SWJ一般为1。 例如STM32F407的&#xff0c;CAN1和CAN2都在在APB1下&#xff0c;频率是42000000 如果想配置成1M波特率&#xff0c;则计算公式为&#xff1a;...

简单好用的折线图绘制!

折线图的概念及作用&#xff1a; 折线图&#xff08;Line Chart&#xff09;是一种常见的图表类型&#xff0c;用于展示数据的变化趋势或时间序列数据。它通过一系列的数据点&#xff08;通常表示为坐标系中的点&#xff09;与这些点之间的线段相连&#xff0c;直观地展示变量…...

Hadoop批量计算实验

参考: Hadoop(一)之实验一CentOS7配置Hadoop系统:配置CentOS和下载安装包_基于虚拟机cents7搭建hadoop实验目的-CSDN博客 --------------------------------------------------------- 一、安装Vmware 二、创建虚拟机 1.安装centos7 ①打开VMware,点击新建虚拟机。 …...

基于rpcapd与wireshark的远程实时抓包的方法

基于rpcapd与wireshark的远程实时抓包的方法 服务端安装wireshark侧设置 嵌入式设备或服务器上没有图形界面&#xff0c;通常使用tcpdump抓包保存为pcap文件后&#xff0c;导出到本地使用wireshark打开分析&#xff0c;rpcapd可与wireshark配合提供一种远程实时抓包的方案&…...

ubuntu多版本安装gcc

1.ubuntu安装gcc 9.3.1 $ sudo apt update $ sudo apt install gcc-9 g-9 二、配置GCC版本 安装完成后&#xff0c;需要使用update-alternatives命令来配置GCC版本。这个命令允许系统在多个安装的版本之间进行选择 1.添加GCC 9.3.1到update-alternatives管理 $ sudo update-a…...

算法刷题Day1

BM47 寻找第k大 第一天就随便记录吧&#xff0c;万事开头难&#xff0c;我好不容易开的头&#xff0c;就别难为自己&#xff0c;去追求高质量了。嘿嘿嘿 题目 传送门 解题思路一&#xff1a;维护一个大小为k的最小堆。最后返回堆顶元素。 代码&#xff1a; # # 代码中的类名…...

泛化调用 :在没有接口的情况下进行RPC调用

什么是泛化调用&#xff1f; 在RPC调用的过程中&#xff0c;调用端向服务端发起请求&#xff0c;首先要通过动态代理&#xff0c;动态代理可以屏蔽RPC处理流程&#xff0c;使得发起远程调用就像调用本地一样。 RPC调用本质&#xff1a;调用端向服务端发送一条请求消息&#x…...

Java 泛型详细解析

泛型的定义 泛型类的定义 下面定义了一个泛型类 Pair&#xff0c;它有一个泛型参数 T。 public class Pair<T> {private T start;private T end; }实际使用的时候就可以给这个 T 指定任何实际的类型&#xff0c;比如下面所示&#xff0c;就指定了实际类型为 LocalDate…...

题解:CF332B Maximum Absurdity

CF332B CF332B 暴力思路 题目要我们找两个不重叠的区间&#xff0c;并使区间的值最大。那我们可以考虑使用双重循环搭配前缀和暴力求最大值。代码如下。 for(int i1;i<n;i) {ll lsum[ik-1]-sum[i-1],maxx;for(int jik;j<n;j){maxxlsum[jk-1]-sum[j-1];if(maxx>ans.…...

Vue 集成和使用 SQLite 的完整指东

1. 引言 SQLite 是一种轻量级的关系型数据库管理系统&#xff0c;以其简单易用、无需服务器等特点广泛应用于嵌入式系统、移动应用和小型应用程序中。在 Web 开发中&#xff0c;尤其是前端应用开发中&#xff0c;SQLite 可以作为客户端本地存储的一种选择&#xff0c;为用户提…...

【JVM什么时候触发YoungGC和FullGC】

YoungGC 年轻代Eden区满&#xff0c;就会触发YoungGC FullGC 老年代空间不足 经过多次GC后的大年龄对象会被放进老年代&#xff0c;或创建的大对象会直接在老年代分配&#xff0c;此时若老年代空间不足&#xff0c;就会触发FullGC。空间分配担保失败 触发YoungGC的时候会进行…...

ubuntu配置网络

1&#xff0c;设置桥接模式 1-1&#xff1a; 确定。 1-2&#xff1a; 编辑--->虚拟网络编辑器 刚安装ubuntu的时候&#xff0c;可能没有任何VMnet. 更改设置的目的&#xff1a; 添加VMnet0&#xff0c;并且设置VMnet为桥接模式--自动桥接。 如果没有VMnet0,选择添加网络…...

网站做301跳转的方法/免费推客推广平台

今天&#xff0c;小编就据目前互联网行业的发展&#xff0c;以及大数据Hadoop分布式集群等等来讲解一下&#xff0c;政企如何搭建大数据计算服务平台。互联网信息技术的迅猛发展&#xff0c;云计算、物联网、智能科技、AI、超级计算机等等的出现和发展&#xff0c;使数据量不断…...

海南省城乡住房建设厅网站首页/新闻稿件代发平台

二叉树 &#xff08;一&#xff09;二叉树 1.二叉树 &#xff08;1&#xff09;每个节点最多只有两个子节点 2.满二叉树 &#xff08;1&#xff09;每个节点只有0个或者2个子节点 3.完全二叉树 &#xff08;1&#xff09;每一层节点缺失的子节点只能在右边 4.完美二叉树 &a…...

php做网站怎么布局/网络违法犯罪举报网站

Python中的字典特点&#xff1a; 速度快&#xff0c;内部使用二分查找的方式 可以用来存储大量的关系型数据 字典是无序的 字典的定义方式&#xff1a; dic dict(name ”zhangsan”, age 19) dic1 dict(((“name”, “zhangsan”), (“age”, 19))) dic2 {“name”:”la…...

网站建设的好处有什么用/引擎seo如何优化

系统流程如下图所示 首先数据交换流程为数据库<—>后台<---->前台 Dao层负责和数据库进行数据交互&#xff0c;services负责事务逻辑处理,action为struts部分&#xff0c;主要负责页面跳转时的数据传送。在web.xml文件中&#xff0c;有 <?xml version"1…...

html5做手机网站/有了域名如何建立网站

给你两个二进制字符串&#xff0c;返回它们的和&#xff08;用二进制表示&#xff09;。 输入为 非空 字符串且只包含数字 1 和 0。 示例 1: 输入: a "11", b "1" 输出: "100"示例 2: 输入: a "1010", b "1011" 输出…...

广州市花都区网站建设公司/百度关键词搜索量查询

将Vim改造为强大的IDE—Vim集成Ctags/Taglist/Cscope/Winmanager/NERDTree/OmniCppComplete1、安装Vim和Vim基本插件 首先安装好Vim和Vim的基本插件。这些使用apt-get安装即可&#xff1a; lingdubuntu:~/arm$sudo apt-get install vim vim-scripts vim-doc 其中vim-scripts是v…...