引言 生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。
问题 假设有这样一个复杂对象, 在对其进行构造时需要对诸多成员变量和嵌套对象进行繁复的初始化工作。 这些初始化代码通常深藏于一个包含众多参数且让人基本看不懂的构造函数中; 甚至还有更糟糕的情况, 那就是这些代码散落在客户端代码的多个位置。
如果为每种可能的对象都创建一个子类,这可能会导致程序变得过于复杂。
例如, 我们来思考如何创建一个 房屋House对象。 建造一栋简单的房屋, 首先你需要建造四面墙和地板, 安装房门和一套窗户, 然后再建造一个屋顶。 但是如果你想要一栋更宽敞更明亮的房屋, 还要有院子和其他设施 (例如暖气、 排水和供电设备), 那又该怎么办呢?
最简单的方法是扩展 房屋基类, 然后创建一系列涵盖所有参数组合的子类。 但最终你将面对相当数量的子类。 任何新增的参数 (例如门廊类型) 都会让这个层次结构更加复杂。
另一种方法则无需生成子类。 你可以在 房屋基类中创建一个包括所有可能参数的超级构造函数, 并用它来控制房屋对象。 这种方法确实可以避免生成子类, 但它却会造成另外一个问题。
拥有大量输入参数的构造函数也有缺陷:这些参数也不是每次都要全部用上的。
通常情况下, 绝大部分的参数都没有使用, 这使得对于构造函数的调用十分不简洁。 例如, 只有很少的房子有游泳池, 因此与游泳池相关的参数十之八九是毫无用处的。 解决方案 生成器模式建议将对象构造代码从产品类中抽取出来, 并将其放在一个名为生成器的独立对象中。
该模式会将对象构造过程划分为一组步骤, 比如 buildWalls创建墙壁和 buildDoor创建房门创建房门等。 每次创建对象时, 你都需要通过生成器对象执行一系列步骤。 重点在于你无需调用所有步骤, 而只需调用创建特定对象配置所需的那些步骤即可。
当你需要创建不同形式的产品时, 其中的一些构造步骤可能需要不同的实现。 例如, 木屋的房门可能需要使用木头制造, 而城堡的房门则必须使用石头制造。
在这种情况下, 你可以创建多个不同的生成器, 用不同方式实现一组相同的创建步骤。 然后你就可以在创建过程中使用这些生成器 (例如按顺序调用多个构造步骤) 来生成不同类型的对象。
例如, 假设第一个建造者使用木头和玻璃制造房屋, 第二个建造者使用石头和钢铁, 而第三个建造者使用黄金和钻石。 在调用同一组步骤后, 第一个建造者会给你一栋普通房屋, 第二个会给你一座小城堡, 而第三个则会给你一座宫殿。 但是, 只有在调用构造步骤的客户端代码可以通过通用接口与建造者进行交互时, 这样的调用才能返回需要的房屋。
项目运行
环境配置:
Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。
项目技术:
JSP + mybatis + Maven +mysql5.7或8.0等等组成,B/S模式 + Maven管理等等。
环境需要
1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。
2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA;
3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可
4.硬件环境:windows 7/8/10 4G内存以上;或者 Mac OS;
5.是否Maven项目: 否;查看源码目录中是否包含pom.xml;若包含,则为maven项目,否则为非maven项目
6.数据库:MySql 5.7/8.0等版本均可;
毕设帮助,指导,本源码分享,调试部署(见文末) 3.4功能需求分析 系统的目标是为管理员和用户搭建一个网上沟通平台,保证双方的安全,并使双方的利益最大化。
3.4.1管理员需求分析 管理员端的功能主要是开放给系统的管理人员使用,能够对用户的进行管理,主要对个人中心、用户管理、咨询师管理、在线咨询管理、测试报告管理、论坛交流、心理测试管理、试题管理、系统管理、考试管理进行查看,修改和删除等,对系统整体运行情况进行了解。管理员用例分析图,如图3-1所示。
图3-1管理员用例分析图
3.4.2用户需求分析 用户登录进入系统可以实现对个人中心、在线咨询管理、测试报告管理进行查看。用户用例分析图,如图3-2所示。
图3-2用户用例分析图
3.4.3咨询师需求分析 咨询师登录进入系统可以对个人中心、咨询师管理、在线咨询管理、测试报告管理、心理测试管理、试题管理、考试管理进行查看。咨询师用例分析图,如图3-3所示。
图3-3咨询师用例分析图
3.5系统流程分析 3.5.1操作流程 首先为系统登录页面。进入页面后,用户可进行登录和注册的操作。点击登录后,页面就会出现一个登录提示框,向用户传达信息:要进行用户名和密码的输入,完成后才可以进行下一步的操作。用户输入完成后,系统会将输入的信息提交给后台,与数据库中的信息记录进行比较判断。判断比较内容主要分为三个方面:从用户名是否为空、输入的密码是否为空、用户名和密码是否匹配三方面进行判断。只有上述三个条件同时满足,数据库中的信息匹配正确,才视为登陆成功,方可完成后续的操作。若以上三种情况有一条不满足,则会提示该次登录错误,就需要进行重新登录。系统登录流程图如图3-4所示:
图3-4登录流程图
3.5.2添加信息流程 然后是添加信息的页面。进入该页面后,页面会出现一个提示框,示意操作者可以进行信息的添加,从而进行下一步的操作。用户输入想要添加的信息后提交,系统会对输入的内容进行检测。如果检测后输入的信息正确,则会出现“添加成功”的提示框,从而可以进行下一步操作;如果系统检测后检测到想要添加的信息不符合规范要求,则会提示报错,需要进行修改后重新添加。添加信息流程图如图3-5所示:
图3-5添加信息流程图
3.5.3删除信息流程 最后为删除信息页面。进入该页面后,用户可以对所要删除的信息进行选择,选择好删除的内容后,会有一个“是否确认删除”的提示框,操作者可以根据自己的意愿来选择“是”或“否”。完成上述操作,系统会自动的对删除的内容进行判断,如果符合删除要求则会成功删除数据记录,并且更新数据库的内容信息;如果删除的数据记录不符合要求,则会有一个“删除失败”的提示框,操作人员需要根据提示来进行修改,修改完成后重新删除知道删除成功。删除信息流程图如图3-6所示:
图3-6删除信息流程图
4 系统设计 4.1 系统体系结构 高校大学生心理测试系统的结构图4-1所示:
图4-1系统结构
登录系统结构图,如图4-2所示:
图4-2登录结构图
4.2 系统总功能结构设计 系统按照用户的实际需求开发而来,贴近生活。从管理员通过正确的账号的密码进入系统,可以使用相关的系统应用。管理员总体负责整体系统的运行维护,统筹协调。
用指针实现将一个3*3的整型矩阵转置。
要求定义并调用函数void move(int *pointer),实现上述矩阵转置的功能。
输出格式:每行数据之间以空格分隔,最后一个数据后面没有空格
输入样例: 输出样例: /*注:给出几个个人感觉比较有用的建议: 1.main函数放在第一个写,原因很简单,一个被调函数可能没感觉甚至先写 被调函数还不用做被调函数的预处理还要简单些,但当被调函数多的时候先写 主函数更符合思维逻辑 2.我会在后面说明一些函数指针和指针函数的个人理解,希望能帮到你理解, 同时也希望得到你的建议*/ #include<stdio.h> void move(int* pointer);//被调函数:做置换 int main() { int A[3][3] = { 0 }; int* point = NULL;//预处理NULL为空 /*建议一定要做预处理,无论是哪种类型! 有些地方不做预处理是不能正常输出的,同时预处理还可以简化后面操作,如: 我们知道0为假,非0为真,例: int A[100] = { 0 };//比如A数组中为题中所要求的全部被判断数字 int panduan[100] = { 0 }; //我们可以预处理成A数组中所有数均不满足条件 这样我们就不需要在后面返回为假的时候的0,只需返回为真时的1(我一般1为真) 这样很省时*/ for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { scanf("%d", &A[i][j]);//输入 } } point = A[0]; /*是不是感觉有问题,怎么变成一维数组了? 其实A[0]、A[1]、A[2],都是0、1、2行的首个元素的地址 包括A也是地址,所以point是指针但后面并没有&取地址符*/ move(point);//调用被调函数 for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { printf("
1. 实时数仓Hologres特点 专注实时场景:数据实时写入、实时更新,写入即可见,与Flink原生集成,支持高吞吐、低延时、有模型的实时数仓开发,满足业务洞察实时性需求。
亚秒级交互式分析:支持海量数据亚秒级交互式分析,无需预计算,支持多维分析、即席分析、探索式分析、MaxCompute加速分析,满足所见即所得分析体验。
统一数据服务出口:支持多维分析、高性能点查、数据检索等多个场景,支持负载隔离,简化数据架构,统一数据访问接口,实践分析服务一体化(HSAP)。
开放生态:标准SQL协议,无缝对接主流BI和SQL开发框架,无需应用重写。支持数据湖场景,支持JSON等半结构化数据,OSS、DLF简易入仓。
2. 实时计算Flink服务 全托管Flink服务:开箱即用、开发远维全周期、计费灵活
丰富的企业级能力:流批一体的一站式开发运维平台、Flink CDC实时入湖入仓、动态CEP助力实时风控/营销、作业自动调优充分利用资源、智能冷断快速定位
性能强劲:内核引擎优化: CPU超秒数十万记录处理能力、Nexmark 测试性能技开源提升200%、状态存储后端优化
100%兼容开源:100%兼容Apache Flink、支持开源 Flink平滑迁移上云、无缝对接主流开源大教据生态
开放被集成能力强:自定义连按器、UXF能力扩展、Open API帮助用户集成自身系统、用户开发能力扩展与沉淀复用、用户自身系统集成
业界认可:中国信通院权威认证、中国唯一进入 Forrester 象限的实时流计算产品、金融实时数仓方案入围工信部信创典型目录
3. 数据仓库概念 数据仓库定义 ( Data Warehouse ):为企业所有决策制定过程,提供所有系统数据支持的战略集合。
传统的离线数仓无法实现当天数据的及时分析数据,所以需要开发实时数仓开填补空缺。
4. 阿里云技术框架 阿里云产品简介类比Flink实时计算平台大数据计算框架Hadoop集群+Flink+调度器Hologres大数据存储框架Kafka+Redis+HBase+ClickHouseDataHub数据流存储Kafka+元数据管理RDS关系型数据库MySqlDataV可视化数据展示工具Tableau、Echarts、Kibana 5. 系统数据流程设计 5. Hologres的购买和基础介绍 后来我总是找不到实例在哪。(我等了两个小时终于实例出来啦)
点击登录实例
点击连接实例
双击 登录库
可以编辑SQL
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' -- 可以根据需要更改模式名称 AND table_type = 'BASE TABLE'; 6. Flink实时计算 开通之后点击立即试用
7. 数据总线Datahub 数据总线datahub是阿里云免费提供的服务,相当于大数据框架中的kafka,可以用作数据的缓存。
进入到datahub的主页面之后,点击项目管理,之后再点击新建项目。填写项目名称之后即可完成创建。
8. 业务表 一共7个表
9. 同步策略 数据同步策略的类型包括:全量同步(每天把完整的数据同步)、增量同步(有一条数据变化就同步过来)
文章目录 计算机计算机基础知识操作系统计算机网络 自考学习与备考考试经历 软考学习与准备考试成果人生成长自主学习解决问题团队合作 总结 计算机 计算机是我学习和应用Java编程的基础,它为我提供了一个强大的工具和平台。在这四年的学习中,我逐渐深入了解了计算机的原理和体系结构,这对我理解Java编程语言的底层实现和优化技巧非常有帮助。
计算机基础知识 在学习Java编程之前,我首先系统地学习了计算机的基本原理、数据结构和算法等基础知识。这些知识使我能够更好地理解Java编程语言的设计理念和运行机制,从而更好地应用Java进行软件开发。
操作系统 操作系统是Java编程的重要环境之一,我学习了操作系统的相关概念和原理,掌握了操作系统与Java编程之间的交互方式。通过对操作系统的学习,我深入了解了进程管理、内存管理和文件系统等概念,这对于编写高效、稳定的Java程序至关重要。
计算机网络 计算机网络是我学习Java编程过程中不可或缺的一部分。我学习了计算机网络的基本原理和协议,掌握了网络通信的基本概念和技术。这让我能够编写基于网络的Java应用程序,实现远程通信、数据传输等功能。
自考 自考是我的一项重要挑战,也是我个人成长的重要经历之一。
学习与备考 在自考的过程中,我需要自主学习和备考各门课程。这对我的自律和学习能力提出了很高的要求。我制定了详细的学习计划,合理安排时间,确保每门课程都能够充分复习和准备。通过自考,我不仅学到了专业知识,也培养了自主学习和解决问题的能力。
考试经历 自考最大的挑战之一是面对紧张的考试。每门课程的考试都是一个重要的机会,需要我克服紧张情绪,发挥出自己的最佳水平。通过自考的考试经历,我逐渐掌握了应对考试压力的方法,例如深呼吸、积极心态等。这些经验对于未来的职业发展和面对其他考试也非常有帮助。
软考 参加软考是我在大学期间进一步提升自身技能的重要途径。
学习与准备 软考涵盖了计算机软件技术的多个领域,要求掌握广泛的知识和技能。为了应对软考的挑战,我积极学习相关的知识和技术,参加培训班和自主学习。通过大量的练习和实践,我逐渐提升了软考所需的编程能力、系统设计和数据库管理等技能。
考试成果 软考考试是一项具有一定难度的考试,需要综合运用所学知识并具备一定的实践经验。我经过努力和准备,成功通过了多门软考科目,获得了相应的资格证书。这不仅对我的个人职业发展有着积极的影响,也增强了我对自己能力的自信。
人生成长 除了计算机知识,四年的Java编程学习也让我在个人成长方面受益匪浅。
自主学习 Java编程是一门不断发展和更新的技术,需要不断学习和跟进最新的发展动态。在学习Java编程的过程中,我培养了自主学习的能力,善于查阅文档、参考优秀的开源项目并进行实践。这种自主学习的能力使我能够不断提升自己的技术水平,跟上技术的发展步伐。
解决问题 Java编程过程中经常会遇到各种问题和挑战,例如程序bug、性能优化、软件设计等。通过解决这些问题,我逐渐培养了分析和解决问题的能力。我学会了合理利用调试工具、查找文档、借鉴他人的经验等方法,将问题一一击破,这为我后续的编程工作打下了坚实的基础。
团队合作 Java编程往往涉及到团队合作的场景,例如多人协同开发、代码版本管理等。通过参与各种项目和团队合作,我学会了有效沟通、协调合作、理解他人代码等技能。这些技能使我能够更好地与团队成员合作,提高工作效率,同时也增强了我的综合素质。
总结 四年的Java编程学习让我不仅掌握了计算机和相关知识,也在个人成长方面有了很大的提升。我相信这些学习和经历将为我未来的职业发展打下坚实的基础,并帮助我在软件开发领域取得更大的成就。通过自考和软考的学习和考试经历,我不仅获得了专业知识和技能,也培养了自律、自主学习和解决问题的能力。这些经历在我的个人成长和职业发展中起到了重要的推动作用。我相信这些挑战和经历将为我未来的发展打下坚实的基础,并帮助我在职业道路上取得更大的成就。我期待着继续学习和成长,为社会的进步贡献自己的力量。
题目 给你一个整数数组 nums 和一个整数 k 。
每一步操作中,你需要从数组中选出和为 k 的两个整数,并将它们移出数组。
返回你可以对数组执行的最大操作数。
示例 1:
输入:nums = [1,2,3,4], k = 5
输出:2
解释:开始时 nums = [1,2,3,4]:
移出 1 和 4 ,之后 nums = [2,3]移出 2 和 3 ,之后 nums = []
不再有和为 5 的数对,因此最多执行 2 次操作。
示例 2: 输入:nums = [3,1,3,4,3], k = 6
输出:1
解释:开始时 nums = [3,1,3,4,3]:
移出前两个 3 ,之后nums = [1,4,3]
不再有和为 6 的数对,因此最多执行 1 次操作。 提示:
1 <= nums.
实验名称 应用sklearn分析竞标数据 实验时间 2023-04-26
(gcc的同学不要抄袭呀!)
一、实验目的 1、掌握skleam转换器的用法。
2、掌握训练集、测试集划分的方法。
3、掌握使用sklearm进行PCA降维的方法。
4、掌握 sklearn 估计器的用法。
5、掌握聚类模型的构建与评价方法。
6、掌握分类模型的构建与评价方法。
7、掌握回归模型的构建与评价方法。
二、实验仪器设备或材料
笔记本电脑,Anaconda软件
三、实验原理
任务1:使用sklearn处理竞标行为数据集。(数据集找你们老师要哦!)
1、需求说明
竞标行为数据集(shill bidding.csv)是网络交易平台eBay为了分析竞标者的竞标行为而收集整理的部分拍卖数据,包括记录ID、竞标者倾向、竞标比率等11个输入特征和I个类别标签,共6321条记录,其特征/标签说明如表6-18所示。通过读取竞标行为数据集,进行训练集和测试集的划分、为后续的模型构建提供训练数据和测试数据;并对数据集进行降维,以适当减少数据的特征维度。
任务2:构建基于竞标行为数据集的K-Means聚类模型。
1、需求说明
使用实训1中的竞标行为数据集,竞标行为标签总共分为2种(0表示正常竞标行为,1表示非正常竟标行为)为了通过竞标者的行为特征将竞标行为划分为簇,选择数据集中的竞标者倾向、竞标比率,连续竞标3个特征,构建K-Means模型,对这3个特征的数据进行聚类,聚集为2个族,实现竞标行为的类别划分,并对聚类模型进行评价,确定最优聚类数目。
任务3:构建基于竞标行为数据集的支持向量机分类模型。
1、需求说明
对实训1中的竞标行为数据集进行训练集和测试集的划分,为了对竞标者的竞标行为进行类别判断、根据训练集构建支持向量机分类模型、通过训练完成的模型判断测试集的竞标行为类别归属,并对分类模型性能进行评价。
1、需求说明
对实训1中的竞标行为数据集进行训练集和测试集的划分,为了对竞标者的竞标行为进行预测.构建线性回归模型,用训练集对线性回归模型进行训练,并对测试集进行预测;计算回归模型评价指标得分,通过得分评价回归模型的优劣。
四、实验内容与步骤
任务1:使用sklearn处理竞标行为数据集。
1、实现思路与步骤
(1)使用pandas库读取竞标行为数据集。
(2)对竞标行为数据集的数据和标签进行划分。
(3)将竞标行为数据集划分为训练集和测试集,测试集数据量占总样本数据量的20%。
(4)对竞标行为数据集进行PCA降维,设定n-components=0.999、即降维后数据能保留的信息为原来的99.9%、并查看降维后的训练集、测试集的大小。
任务2:构建基于竞标行为数据集的K-Means聚类模型。
1、实现思路与步骤
(1)选取竟标行为数据集中的竞标者倾向、竞标比率、连续竞标、类别特征。
(2)构建K-Means模型。
(3)使用ARl评价法评价建立的 K-Means模型。
(4)使用V-measure评分评价建立的K-Means模型。
(5)使用FMI评价法评价建立的 K-Means模型,并在聚类数目为1-3类时,确定最优聚类数目。
任务3:构建基于竞标行为数据集的支持向量机分类模型。
1、实现思路与步骤
(1)标准差标准化构建的训练集和测试集。
(2)构建支持向量机模刑,并预测测试集前10个数据的结果。
(3)打印分类模型评价报告、评价分类模型性能。
任务4:构建基于竞标行为数据集的回归模型。
1、实现思路与步骤
(1)根据竟标行为训练集构建线性回归模型,并预测测试集结果。
(2)分别计算线性回归模型各自的平均绝对误差、均方误差、R值。
(3)根据得分,判定模型的性能优劣。
五、实验结果与分析
任务一:
任务二:
1、ari是调整兰德指数,用于衡量聚类算法的性能。在此处评估中,ari的值为-0.004654458188395929,表示聚类效果较差,可能存在重叠或不明显的聚类。
2、v-measure是精确度和召回率的加权平均数,用于衡量聚类的准确性和完整性。在此处评估中,v-measure的值为0.000895321967423075,表示聚类效果较差,存在许多错误的分类。
3、Fmi是fowlkes-mallows index的缩写,用于度量聚类结果与真实分类之间的相似度。在此处评估中,最佳的fmi得分为1对应于第一种情况。
可以看出,这里的聚类结果并不是很好,ari和v-measure得分都较低,其中fmi指标在分为1组时得到了较高的分数。考虑重复执行该聚类算法,或者尝试使用其他算法进行聚类操作可能会改善结果。
任务三:
上图结果是支持向量机(svm)对客户数据进行分类后得出的分类报告。下面是该分类报告的含义。
1、precision:该指标衡量分类器预测为正样本中实际为正样本的比例,即正确预测 positive 的数量除以预测为 positive 的总数,代表分类器的准确性。
在自定义IP出现以上错误时可以通过双击模块clk属性
如果是灰色无法二次编辑时,在封装IP时,选择以下菜单
写Python程序的时候, 我们经常需要写日志, 以便调试程序,发现问题,以及查看程序的运行状态。
Python自带了logging模块,可以将日志保存到.txt文件中, 也可以输入到界面上。
我们希望日志有一定的格式, 比如下面这样的格式输出:
2013-04-24 09:30:28,071 INFO This is a info message 2013-04-24 09:30:28,071 WARNING This is a warning message 2013-04-24 09:30:28,071 ERROR This is a error message 2013-04-24 09:30:28,071 CRITICAL This is a critical message Python 代码
# -* - coding: UTF-8 -* - import logging logger = logging.getLogger() # 先在C盘下面新建一个文件夹,叫做test handler = logging.FileHandler("c:\\test\\log.txt") logger.addHandler(handler) # Formatter的文档说明。这里有三项:时间,信息级别,日志信息 formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') handler.setFormatter(formatter) # 设置日志输出的级别, 写入日志时,小于指定级别的信息将被忽略。 # 因此为了输出想要的日志级别一定, 要设置好此参数。这里我设为NOTSET(值为0),也就是想输出所有信息 logger.
历史文章(文章累计490+)
《国内最全的Spring Boot系列之一》
《国内最全的Spring Boot系列之二》
《国内最全的Spring Boot系列之三》
《国内最全的Spring Boot系列之四》
《国内最全的Spring Boot系列之五》
《国内最全的Spring Boot系列之六》
Mybatis-Plus自动填充功能配置和使用 [MyBatis-Plus系列] - 第494篇
15篇MyBatis-Plus系列集合篇「值得收藏学习」
全文检索[ES系列] - 第495篇
师傅:徒儿,看你满面愁容,这是怎么了?
悟纤:如果对于现状不满怎么办?
师傅:如果一个人对自己的现状不满,那么就应该想办法改变自己,改变自己现在自身的情况。
师傅:一个人,如果你觉得你所处地方周围的环境你不满意,那么你就应该跳出舒适区,改变自己,变得优秀,走出这个你不满意的环境,优秀到你随时都有能力跳出你不想融入的圈子。
师傅:世界上没有绝对不变的事物,只有善变,才能适应这个社会。善于改变,善于变化,变得优秀。当你不能改变周围的环境的时候,那么,就改变自己吧。这个世界上可能多的是想改变世界的人,想改变自己的可能不多。但是,如果你连自己都不能改变,那想要改变世界的想法也就太遥远了。先改变自己,才有可能改变周围的环境。
师傅:最后就是心态了,如果事已成定局,那么就改变自己的心态。改变自己对这个事情的看法,不是事情本身影响了你的心情,而是你对这个事情的看法。
悟纤:听师傅一席话,胜学十年书。
师傅:活到老,学到老,还有好多没学了。
导读
Hi,大家好,我是悟纤。我就是我,不一样的烟火。我就是我,与众不同的小苹果。
在前一小节学习了全文检索的基本概念,这一节就可以来了解一下什么是ES?
一、ElasticSearch介绍
ElasticSearch(简称ES)是一个开源的分布式搜索和数据分析引擎,是用Java开发并且是当前最流行的开源的企业级搜索引擎,能够达到近实时搜索,它专门设计用于处理大规模的文本数据和实现高性能的全文检索。
官方网站:
https://www.elastic.co/
下载地址:
https://www.elastic.co/cn/downloads/past-releases#elasticsearch
2.1 ElasticSearch特点和优势
以下是一些 Elasticsearch 的特点和优势:
· 分布式架构:Elasticsearch 是一个分布式系统,可以轻松地水平扩展,处理大规模的数据集和高并发的查询请求。
· 全文检索功能:Elasticsearch 提供了强大的全文检索功能,包括分词、词项查询、模糊匹配、多字段搜索等,并支持丰富的查询语法和过滤器。
· 多语言支持:Elasticsearch 支持多种语言的分词器和语言处理器,可以很好地处理不同语言的文本数据。
· 高性能:Elasticsearch 使用倒排索引和缓存等技术,具有快速的搜索速度和高效的查询性能。
· 实时性:Elasticsearch 支持实时索引和搜索,可以几乎实时地将文档添加到索引中,并立即可见。
· 易用性:Elasticsearch 提供了简单易用的 RESTful API,方便进行索引管理、查询操作和数据分析。
2.2搜索引擎排名
可以通过网站看到搜索引擎的排名:
https://db-engines.com/en/ranking/search+engine
2.3 ElasticSearch应用场景
这真是一场大汗淋漓的debug,刚写完发现运行结果和预期不符,就一直在debug,后来就搜索发现,还可以这样写
outer: for(------------){ for(-----------){ ----; ----; break outer; } }
黑客修炼手册——成为高级黑客的必由之路
诗词模块 《观潮》 宋·苏轼
庐山烟雨浙江潮,未至千般恨不消。
到得还来别无事,庐山烟雨浙江潮。
讲座主题 寒冬时节,随着科技的迅猛发展,网络安全问题逐渐成为社会关注的焦点。恶意黑客、数据泄露、网络攻击等挑战不断涌现,给个人和企业的信息安全带来了巨大的风险。
近期,国际网络安全专家们共同发出警告,提醒人们要时刻保持警惕。据统计,全球范围内的网络攻击事件在冬季呈现出明显的上升趋势。2023年11月24日,上海杉达学院嘉善光彪学院报告厅,我们伴随着上课铃声,来到了赖杨健老师的讲座课堂,主题为《网络安全行业与职业发展》。
01、演讲嘉宾 赖老师简单的介绍了自己,他是一位技术经验非常丰富的,曾任职于各大安全公司的信息安全专家。
本次的讲座的主要内容是网络安全行业概述、人才分类及职业发展等五个部分开展。
02、网络安全行业 赖老师通过五个方面阐述了网络安全行业,并分析了何为网络空间、网络安全的国际形势,国家之间对抗升级,网络空间成为科技利益、数字主权争夺和再分配的主战场,网络空间安全成为国家安全和经济的基础保障。
03、人才紧缺 随着技术的发展,网络威胁变得更加复杂和难以预测。对新威胁和攻击手法的不断涌现导致需要更多的专业人才来应对这些挑战。网络安全进攻型人才紧缺、供给太少是网络安全行业的主要问题。必须提高网络安全教育和培训的机会,以培养更多的专业人才。促使行业和学术界更紧密地合作,共享信息和最佳实践,以加强整个生态系统的网络安全。
04、培养能力 赖老师通过《离骚》中的“路漫漫其修远兮,吾将上下而求索”,告诉我们人生的道路可能会很漫长,修行的路途也许会很遥远,但要坚定地向前迈进,勇往直前,不畏艰险,努力探索,寻求更好的未来。终生学习,从未止步。
05、黑客攻击 网络大事件WannaCry病毒席卷全球,近十年赖影响范围伟大的一猜黑客攻击事件:全球共有150多个国家超多30万台电脑感染。网络攻击的形式不断演变,攻击者采用越来越复杂、难以察觉的手段。恶意软件、勒索软件、社交工程等攻击方式层出不穷,使得网络防御更加困难。一些国家和政治组织也积极投入网络攻击领域,进行网络侦察、信息战等活动,给其他国家的关键基础设施和信息系统带来威胁。
关注我们! 团队成立于2016年
WIS-HUNTER——智慧网络病毒猎手
拥有最全的信息安全服务内容
具备强大的安全研究团队
公司下辖多个实验室
其中杀手锏攻防实验室拥有大批漏洞发掘和分析人员,是独立发掘CVE和CNVD漏洞数量的团队,拥有覆盖8*N人的专业安全服务团队
理念
以小博大,技术是杀手锏。
文化
明白人——
知其然,知其所以然!
不要迷惑于表象而要洞察事务的本质,
要有文盲学习知识的心态,
有时我们的学历,
是我们学习过程中 最大的障碍。
出品人——
本人出品,必属上品!
有自我荣誉意识、追求卓越意识。
乔布斯:人这辈子没法做太多事情,所以每一件都要做到精彩绝伦。
简述:联想拯救者Y7000P用u盘安装ubuntu双系统后发现右上角无wifi图标无法连接无线网络,在查询无线网卡型号为realtek 8852ce后安装相应网卡驱动,问题解决。
以下是本人解决该问题的过程
一、电脑型号 联想拯救者Y7000P 13代酷睿i7 RTX4060
二、无线网卡驱动 1.在终端查询电脑无线网卡型号 常规更新包:
sudo apt-get update sudo apt-get upgrade 查询网卡型号
lspci | grep -i net 输出效果:
Network controller后面便是电脑无线网卡型号,"c582"即“Realtek 8852ce”
2.网卡驱动安装 在网上找了很久没有找到一个合适的官方驱动,最后在Github上找到一个需要自己编译的
(1)安装依赖库 sudo apt-get install make gcc linux-header-$(uname -r) build-essential git 从Github上下载驱动
git clone https://github.com/lwfinger/rtw89.git 如果能够顺利clone下来可以在“下载(Download)”中看到一个"rtw89"的文件夹
如果无法clone可以尝试在git clone前加sudo再执行一次代码
还是无法clone下来的可以直接进链接下载压缩包:https://github.com/lwfinger/rtw89
注:压缩包最好解压在主目录或者下载里面,否则可能编译失败
(2)安装驱动 cd rtw89 #进入rtw89这个文件夹 make sudo make install 这一步一开始我把文件夹放在桌面编译失败(报错)了,后来移动到“下载”文件夹后就直接编译成功了(玄学,解释不了),有其他编译的报错建议百度找找解决方法。
有其他博主对rtw89中的部分文件进行了部分修改成功编译,由于我没修改就能编译成功这里不清楚具体是否有用,留个链接给大家参考:https://blog.csdn.net/I_O_fly/article/details/124448964
(3)安装firmware files 下载链接:https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/rtw89
下载文件:rtw8852c_fw.bin
将文件下载拷贝到 /lib/firmware/rtw89 中
在拷贝过程中可能需要先更改rtw89文件夹的权限:
chmod -R 777 /lib/firmware/rtw89 (4)启动驱动 sudo modprobe -v rtw_8852ce (5)重启 重启之后点右上角倒三角就能看到wifi连接图标
23-12-11 17:25:18.179 [https-jsse-nio-8970-exec-7] INFO c.g.wvp.vmp.gb28181.transmit.cmd.impl.SIPCommander - 34010200001130000006_34010200001310000006 分配的ZLM为: wvpmediaserver001 [10.30.2.8:30406] 2023-12-11 17:25:18.337 [wvp-9] INFO c.g.w.v.g.t.e.r.impl.InviteResponseProcessor - [回复ack] 34010200001130000006-> 10.60.3.61:5060 2023-12-11 17:25:32.706 [wvp-22] INFO c.g.w.v.g.t.e.r.i.m.n.c.KeepaliveNotifyMessageHandler - [收到心跳], device: 34010200001130000006, callId: MjU1ODJmYWQ0YmY0ZmFjZGQ3MzIwNTBkZGU3MDQ1MmU. 2023-12-11 17:25:33.131 [https-jsse-nio-8970-exec-52] INFO com.gbcom.wvp.vmp.media.zlm.ZLMHttpHookListener - [ZLM HOOK] rtpServer收流超时:wvpmediaserver001->34010200001130000006_34010200001310000006(0) 2023-12-11 17:25:36.292 [ThreadPoolTaskScheduler-88] INFO com.gbcom.wvp.vmp.service.impl.PlayServiceImpl - [点播超时] 收流超时 deviceId: 34010200001130000006, channelId: 34010200001310000006,码流类型:主码流,端口:30406, SSRC: 0102004686 2023-12-11 17:25:48.186 [wvp-18] INFO c.g.w.v.g.t.e.r.i.m.n.c.KeepaliveNotifyMessageHandler - [收到心跳], device: 34010200001130000006, callId: MjU1ODJmYWQ0YmY0ZmFjZGQ3MzIwNTBkZGU3MDQ1MmU. 2023-12-11 17:25:55.102 [wvp-20] INFO c.g.w.v.g.t.e.r.impl.RegisterRequestProcessor - [注册请求]设备:34010200001130000006, 开始处理: 10.
本想着直接打包上传到CSDN,可现在资源审核好严格,直接给毙了。
随便贴点代码水水。到发文时为止,已汉化内容:
HAL库驱动头文件(hal.h文件,48个)
HAL库驱动文件(hal.c 文件,42个)
外设访问层头文件(stm32f1xxx.h 寄存器宏定义文件,15个)
工具链向量表(.s文件,43个)
LL库(正在进行)
...
本汉化只对库中注释进行汉化,所有原版校对完成的文件,实际代码均与官方原库一致 使用方法按官方库即可。(除部分原版代码报错的调整,修改条目见:使用说明)
源库文件来自ST官网:
版本:V1.8.0 + V1.8.5更新补丁(2023/10/7(官方更新记录2023/4/7))
长期下载链接(更新地址):
STM32F1汉化版HAL库https://10heart.lanzouj.com/s/stm32f1-cnstm32f1xx_hal_exti.c & stm32f1xx_hal_exti.h 源码注释汉化版
/** ****************************************************************************** * @file stm32f1xx_hal_exti.c * @author MCD Application Team * @brief HAL库 EXTI 模块驱动 * 本文件提供固件函数,用于管理扩展中断和事件控制器(EXTI)外设的以下功能: * + 初始化和反初始化函数 * + IO 操作函数 * ****************************************************************************** * @attention * * 版权所有 (c) 2019 STMicroelectronics。 * 保留所有权利。 * * 本软件根据可以在此软件组件的根目录中找到的 LICENSE 文件中的条款进行许可。 * 如果此软件没有附带 LICENSE 文件,则按原样提供。 * ****************************************************************************** @verbatim ============================================================================== ##### EXTI 外设特性 ##### ============================================================================== [.
idea 编写代码过程中,java 类或接口引用编译报错,又不影响运行,最常见的原因是内存异常
直接:File -> Invalidate Caches / Restart...
#!/bin/bash # repo_path="/home/workspace/cp_tcui_bp" branch_list=("develop-t951d2fe9e" "develop-1" "public-1" "public-2" ) function_name="SetVolume(volume / 100);" # cd $repo_path # 遍历分支列表 for branch in "${branch_list[@]}" do # 切换到指定分支 git checkout $branch git pull --prune # 检查代码中的函数 function_found=$(grep -nir "$function_name" ./softwinner/eyesee-mpp/awcdr/apps.cpp) # 输出结果 if [[ -n "$function_found" ]]; then echo "在分支[$branch]中找到函数[$function_name]" echo "$function_found" else echo "在分支[$branch]中未找到函数[$function_name]" fi done
在本次双十一之前,我们上线了新版的批处理框架,完整支撑了大促的招商。通过SDK接入,可以直接在业务应用中实现任务逻辑,接入便捷;通过中心化调度与任务分发,处理过程提效明显。
背景
在B端系统中,批处理能力是不可或缺的,它可以帮助用户批量完成一系列动作,降低重复操作的成本。在大促招商系统中,我们也需要一套在线批处理框架,来支持商家的批量商品报名、批量主图打标、一键发布、导出已报商品等操作,让商家可以批量上传数据、管理操作记录、查看批量操作的结果明细。这些任务输入数据的来源五花八门,有Excel、DB、OpenSearch等,框架需要能支持各种类型输入数据的解析。同时,招商系统的应用数量较多,需要能同时支持各个域的应用便捷接入,最好是只需要引包,然后实现任务逻辑即可。在大数据量的场景下,框架需要能支持对不同类型的任务实例精细化调度,同时保证系统的吞吐量和稳定性。
整体方案
▐ 架构设计 业务容器为接入框架的应用,任务中心是批处理框架的中心应用。实例的调度、状态变更在任务中心完成,方便做中心化管理;实例的执行逻辑在业务容器中实现,所以在执行时需要回调业务容器。
▐ 模型设计 要在单条数据项维度调度任务实例,除了任务注册信息、任务实例外,还需要引入子任务实例的模型。任务注册信息对象含有某个任务的任务类型、执行限流值等信息。用户每次批量上传数据都会生成一个主任务实例,单条数据项对应一个子任务实例。
▐ 主要流程 核心流程借鉴了MapReduce的思想,将一个大任务拆分后分发到多机去执行,最后再进行结果汇总。业务容器在接入时需要实现一个任务的主实例拆分、子实例执行和结果合并逻辑。主实例拆分时会将用户输入数据解析为子实例,落DB存储;子实例执行是单条数据项的执行逻辑;结果合并是将子实例的处理结果统计后展示(如生成任务明细Excel)。
实例被调度触发后任务中心会调用业务容器中实现的主实例拆分方法,主实例被拆分后需要分批回传数据。任务中心执行实例时会将子实例扫出来,通过rocketmq自发自收将子实例分发到任务中心的整个集群,接到消息后调用业务容器执行子实例,拿到结果后更新子实例状态,消费成功。通过ScheduleX任务定时扫描执行中主实例的子实例状态,当子实例全部执行完成后回调业务容器执行结果合并逻辑,最终将任务归档。
▐ 状态机 主任务
子任务
关键技术点
▐ 调度执行 限流组件 限流组件使用的是guava包中的实现,任务注册时需要分别配置主实例和子实例执行的限流值,限流也在任务类型维度来做,调度时根据任务的key取到对应的限流器。限流器缓存在机器本地,过期后重新查询任务注册信息,新建限流器。目前只在单机维度做了限流,用集群限流数除以任务中心的集群机器数,得到单机限流值。
主实例调度 任务实例创建后,会尝试获取一次令牌,如果能获取到,那主实例会直接被触发,执行后续流程。如果没有获取到令牌,任务会停留在待触发状态,等待ScheduleX任务定时捞起重新尝试执行。
子实例调度
主实例在执行时会先在任务中心通过rocketmq将所有子实例分发到整个集群,然后同步调用业务容器执行并获取到子实例的结果。子实例的限流是通过控制消息消费速率实现的。在任务中心消费rocketmq时阻塞获取令牌。因为所有任务类型共用一个topic,消息分发速率也做了上限控制,否则大实例会导致消息积压从而阻塞其他类型任务的执行。
如果在更新子实例状态前机器重启,利用mq的重试机制,对于幂等的任务类型,可直接重新执行,不支持幂等的任务类型在消息重试时子实例直接更新为失败即可。
▐ 中心与客户端通信 执行任务的实现逻辑时,需要回调业务容器,SDK中需要有支持供任务中心主动发起的通信方式。具体实现为:
客户端侧:提供Dubbo接口,业务应用启动时注册服务,用Dubbo的group区分不同应用(group不能重复,所以直接使用应用名称作为group)
任务中心侧:注册为所有业务应用服务的消费者,在需要回调业务容器时,先根据任务注册的应用找到对应消费者,通过消费者向业务应用发起调用
主实例的拆分和结果合并采用异步调用,子实例考虑到已经是拆分后的结果,目前只支持同步调用。
▐ 实例探活 考虑到主实例的拆分和结果合并执行时间较长,极端场景下有几十万条数据的读写,所以主实例的拆分和结果合并对客户端的调用都是异步的。在异步场景下需要考虑如何对业务应用进行探活并重试,否则一旦机器重启,正在执行的任务实例便会停留在中间状态,产生大量脏数据。
探活采用的方案是客户端侧上报心跳结合任务中心侧定时任务检测心跳。客户端接收到请求后会在本地定时上报任务实例的心跳,即更新DB中实例的心跳时间,执行结束后不再上报。任务中心通过ScheduleX任务扫表检测心跳超时的任务实例,重新向客户端发起请求。
以上解决的是业务应用重启时实例执行中断的问题,如果任务中心应用重启,也会导致对实例的部分操作中断(如子实例分发),同样也用心跳时间探活来解决,对超时的实例,重新执行当前状态的操作,防止实例永久停留在中间状态。
▐ 客户端实现 业务容器接入时,只需要实现SDK中的MapReduceTask类并实现主任务实例拆分、子任务实例执行和结果合并的方法,其余逻辑在SDK中内置,无需关心。定义类时还需要声明任务类型的唯一标识key,用于在客户端匹配任务类型和具体实现。具体demo如下:
@BatchTask(key = "myDemo") public class MyDemo implements MapReduceTask { /** * 主任务实例拆分 * * @param context context * @return {@link TaskResult} */ @Override public TaskResult processInstance(ExecuteContext executeContext) { while (true) { // 分批读取输入数据 .
这章是接上一章,使用RPC包,序列化中没有详细去讲,因为这一块需要看的和学习的地方很多。并且这一块是RPC中可以说是最重要的一块,也是性能的重要影响因子。今天这篇主要会讲其使用方式。
文章目录 Protocol Buffers V3 背景以及概念如何使用?分配字段编号指定字段规则 数据类型`标量类型``复合类型`枚举其他消息类型嵌套类型更新消息类型未知字段Anyoneofoneof 特性向后兼容性问题 Maps JSON 映射 Protocol Buffers V3 背景以及概念 序列化是系统通信的基础组件,在大数据、AI框架和云原生等分布式系统中广泛使用。
当对象需要跨进程、跨语言、跨节点传输、持久化、状态读写、复制时,都需要进行序列化,其性能和易用性影响运行效率和开发效率。
但是对于序列化框架而言,业内将其分为两类:静态序列化框架,动态序列化框架。
其中各有优缺点:
静态序列化框架 不支持对象引用和多态、需要提前生成代码等原因,无法作为领域对象直接面向应用进行跨语言开发常见的有:protobuf、flatbuffer、thrift 动态序列化框架 提供了易用性和动态性,但不支持跨语言,且性能存在显著不足,并不能满足高吞吐、低延迟和大规模数据传输场景需求常见的有:JDK序列化、Kryo、Fst、Hessian、Pickle 但是前几天阿里推出了Fury,号称比JDK快了170倍,并且兼具静态序列化和动态序列化的优点。这个下一章会讲。目前的gRPC框架是用protobuf搭建的。所以咱们先让自己的项目成功运行起来再说。所以这个后面再说。
Protocol Buffers是google开源的一种结构数据序列化机制,可跨语言、跨平台。
相比XML、JSON、Thrift等其他序列化格式,Protocol Buffers的序列化和反序列化性能是很高的,且Protocol Buffers序列化后是二进制流,因此数据大小和传输速度是很好的。
所以它非常适合在数据存储或 RPC 数据交换的场景下使用。
以下使用手法是翻译自官网
如何使用? 定义一个 .proto 文件
定义一个搜索请求消息格式,其中每个搜索请求都包含:
一个查询词字符串你感兴趣的查询结果所在的特定页码数每一页应展示的结果数 syntax = "proto3"; message SearchRequest { string query = 1; int32 page_number = 2; int32 result_per_page = 3; } 文件的第一行指定使用 proto3 语法。 如果不这样写,protocol buffer编译器将假定你使用 proto2。这个声明必须是文件的第一个非空非注释行。
SearchRequest 消息定义指定了三个字段(名称/值对) ,每个字段表示希望包含在此类消息中的每一段数据。每个字段都有一个名称和一个类型 指定字段类型:
两个整数page_number 和 result_per_page和一个字符串query(上面的例子)但是也可以为字段指定组合类型,包括枚举和其他消息类型 proto3语法主要包括:
在创建 Django 框架项目时,db.sqlite3 文件是 Django 默认创建的数据库文件。它是一个轻量级的 SQLite 数据库文件,用于存储项目中的数据。
Django 采用了一种称为 ORM(对象关系映射)的技术,它允许开发者使用 Python 代码来定义数据库模型(Model),而不需要直接编写 SQL 查询语句。为了将这些模型映射到实际的数据库表中,Django 提供了内置的数据库后端支持,其中默认的后端就是 SQLite。
当您创建 Django 项目时,默认情况下会生成一个 settings.py 文件,其中包含了数据库相关的配置信息,如数据库类型、连接设置等。在这个配置中,Django 默认将数据库配置为使用 SQLite,并自动在项目根目录下创建 db.sqlite3 文件作为数据库文件。
在实际开发中,您可以选择其他更适合您项目需求的数据库,如 MySQL、PostgreSQL 等,并相应地修改配置文件中的数据库设置。但对于一些小型或简单的项目,SQLite 是一个方便快捷的选择,因为它不需要额外的服务器配置,并且数据库文件可以直接嵌入到项目中。
总之,db.sqlite3 文件在创建 Django 框架时出现是因为 Django 默认使用了 SQLite 作为数据库后端,并自动创建了该文件用于存储项目数据。
上文 java简述springboot内置数据库 并举例启动h2内存数据环境 我们启了一个H2的数据库环境
我们要登录进去的话 还需要调整一些配置 让它初始化
在 application 配置文件中加上对应配置
spring: datasource: url: jdbc:h2:~/test hikari: driver-class-name: org.h2.Driver username: root password: 123456 这里 注意 url就是数据库 JDBC的URL
然后 driver-class-name是驱动类名称
要根据启动情况查看并初始化
然后我们重启项目
继续访问 项目 地址+端口/h2
到界面下 输入自己设置的用户名和密码 然后点击下面登录
我们就进来了
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.14.0</version> </dependency> <dependency> <groupId>net.lingala.zip4j</groupId> <artifactId>zip4j</artifactId> <version>2.11.5</version> </dependency> import net.lingala.zip4j.ZipFile; import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.model.FileHeader; import net.lingala.zip4j.model.ZipParameters; import net.lingala.zip4j.model.enums.CompressionLevel; import net.lingala.zip4j.model.enums.CompressionMethod; import net.lingala.zip4j.model.enums.EncryptionMethod; import org.apache.commons.lang3.StringUtils; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; /** * zip 压缩包处理 */ public class ZipUtils { /** * 压缩 - 带目录 */ public static String zipDir(String dirPath, String zipPath, String password) { try { File dirFile = new File(dirPath); if (!
今天分享的AI系列深度研究报告:《AI终端行业专题报告:从大模型到智能体,端侧算力助力AI规模化应用》。
(报告出品方:国信证券)
报告共计:28页
AI Agent 元年,端侧 AI 支撑规模化扩张 从大模型(LLM)到智能体(Agent),智能助手的下一程
人工智能(AI)在用户软件使用方式上即将带来的根本性变革。比尔·盖茨在今年11 月提出,尽管软件已经经过了几十年的迭代,但使用方式仍然较原始,例如,当用户需要完成特定的任务时,需要告诉设备应该使用哪个应用程序。未来,用户不必再为不同的任务使用不同的应用程序,只需以日常语言告诉设备想要做什么,软件将能够因其对用户生活的深入了解而作出个性化响应。任何在线的人都将能够拥有一个 AI 智能体,由先进人工智能驱动的个人助手。
未来,AI 智能体更倾向于是一种“代理”(agents),与当前AI工具(bot)有所差异。Bot 仅限于单一应用程序,并且通常只在用户输入特定单词或寻求帮助时才介入。这些工具不会记住用户历史上如何使用它们,也不会变得更好或学习用户的任何偏好。而 AI Agent 更加智能:1)它们是主动的,能够在用户提问之前就提出建议;2)它们能够跨应用程序完成任务;3)它会随着时间的推移而改进,因为它们记得用户的活动,并识别其行为中的意图和模式。
百模大战只是起点,A Agent 完成执行落地的完整闭环。LLM 初期,大家普遍认为 LLM 是通向通用人工智能的路径,但大模型只能被动的响应查询,可以完成对话、写故事、生成代码,比传统 AI 模型具有更强的理解能力和创造能力,但并不能直接到达 AGI(通用人工智能)的理想目标。而以 AutoGPT 和 BabyAGI 等项目为代表的 LAM 模型(Large-Action Models/Large-Agent Models),将LLM作为 Agent的中心,将复杂任务分解,在每个子步骤完成自主决策和执行,形成了具有多领域、多模态执行力的 AI Agent。
对于智能体的构建,高领人工智能学院提出了一个由四部分组成的框架,分别是:
1)表示智能体属性的配置模块(Profile),旨在识别智能体是什么角色;
2)存储历史信息的记忆模块(Memory),可将智能体置于动态环境中,使智能体能够回忆过去,帮助智能体积累经验、实现自我进化,并以更加一致、合理、有效的方式完成任务;
3)制定未来行动策略的规划模块(Planning),将复杂问题分解为简单的子任务形成决策;
4) 执行规划决定的行动模块(Action),负责将智能体的决策转化为具体的输出。
目前,基于 LLM 的 Agent 大多仍处于实验和概念验证的阶段,但相关的生态正在 快速丰富,围绕 Agent 的研究工作也持续推进,2023 年可谓是 AI Agent 的元年, 大量 Agent 被推出。
OpenAI 推出 GPTs,搭建通向 AI Agent 终局的桥梁
GPTs在目前能力有限的AI 和未来可能出现的Autonomos Al Agent 之间架起了一座桥梁。2023 年 11 月7 日,penAI 举行了首届开发者日,正式发布了自定义 GPTGPTs。无需代码,用户可以根据自己的指令、外部知识创建自定义版本的ChatGPT,这一功能被称为 GPTs。它们允许为特定目的构建定制化 AI 机器人,而无需高级编码。同时,OpenAI 也会在本月底上线 GPT Store,让开发者们分享、发布自己创建的 GPTs。
前言介绍(如果对你有帮助,请给我点点赞) 当我们在做Java项目时,经常需要对集合进行操作。而对于List集合来说,Stream流提供了一系列便捷的方法,可以帮助我们快速地完成集合的筛选、排序、聚合等操作。但是,由于Stream流的语法比较复杂,有时候会给我们带来一定的困扰。
为了解决这个问题,我在做项目的过程中,通过学习和总结,封装了一些常用的Stream流操作方法。这些方法可以让我们更加方便地对List集合进行处理,提高开发效率并减少出错的风险。
在下面的文档中,我将分享这些方法的实现思路和使用方法,希望能够对大家在日常开发中遇到的类似问题有所帮助
1、方法示例 【 批量修改集合对象的某个值 】
public static void main(String[] args) { //创建假数据, 对象属性为 id , name TUser u1 = new TUser("1","张三"); TUser u2 = new TUser("2","李四"); TUser u3 = new TUser("3","王五"); TUser u4 = new TUser("4","赵六"); List<TUser> userList = new ArrayList<>(); //将对象添加到集合中 userList.add(u1);userList.add(u2);userList.add(u3);userList.add(u4); //TODO 引用【批量修改集合对象的某个值】,实现将集合中所有对象的name修改为 坤哥 //参数1:要处理的集合 //参数2:要修改的属性 //参数3:修改的值 setListObjectByProperty(userList,TUser::setName,"坤哥"); for (TUser tUser : userList) { System.out.println("修改后的对象:" + tUser); } } 输出结果如下:
修改后的对象:TUser{id='1', name='坤哥'} 修改后的对象:TUser{id='2', name='坤哥'} 修改后的对象:TUser{id='3', name='坤哥'} 修改后的对象:TUser{id='4', name='坤哥'} 2、方法封装 import org.
今天分享的AI系列深度研究报告:《AI大模型专题:原生多模态大模型Gemini》。
(报告出品方:谷歌DeepMind)
报告共计:68页
模型架构 Gemini 模型建立在 Transformer 解码器(Vaswani 等人,2017)之上,通过架构和模型优化的改进得 到增强,以实现大规模的稳定训练,并在 Google 的张量处理单元上优化推理。它们经过训练以支 持 32k 上下文长度,采用高效的注意力机制(例如,多查询注意力(Shazeer, 2019))。我们的第一个 版本,Gemini 1.0,包括三种主要尺寸,以支持广泛的应用程序。
Gemini 模型经过训练,可以适应文本输入与各种各样的音频和视觉输入交织在一起,比如自然 图像、图表、截图、pdf 和视频,它们可以产生文本和图像输出(见图 2)。Gemini 模型的视觉编码 灵感来自我们自己在 Flamingo (Alayrac 等人,2022)、CoCa (Yu 等人,2022a)和 PaLI (Chen 等人, 2022)上的基础工作。有一个重要的区别,即模型从一开始就是多模态的,并且可以使用离散的图 像标记原生输出图像(Ramesh et al., 2021;Yu et al., 2022b)。
视频理解是通过将视频编码为大上下文窗口中的一系列帧来完成的。视频帧或图像可以与文本 或音频自然交错,作为模型输入的一部分。模型可以处理可变的输入分辨率,以便花费更多的计算 需要细粒度理解的任务。此外,Gemini 可以直接从通用语音模型(USM) (Zhang et al., 2023)特征中 摄取 16kHz 的音频信号。这使得模型能够捕捉音频被天真地映射到文本输入时通常会丢失的细微 差别(例如,请参阅网站上的音频理解演示)。
训练 Gemini 系列模型需要在训练算法、数据集和基础设施方面进行创新。对于 Pro 模型,我们 的基础设施和学习算法的固有可扩展性使我们能够在几周内完成预训练,利用 Ultra 的一小部分资 源。Nano 系列模型利用蒸馏和训练算法的额外进步,为各种任务(如摘要和阅读理解)生产一流的小 型语言模型,为我们的下一代设备体验提供动力。
培训基础设施 我们使用 TPUv5e 和 TPUv4 (Jouppi 等人,2023)来训练 Gemini 模型,具体取决于它们的大小和 配置。GeminiUltra 训练中心在多个数据中心使用了大量的 TPUv4 加速器。这代表了我们之前的 旗舰型号 PaLM-2 的规模显着增加,这带来了新的基础设施挑战。加速器数量的增加会导致整个 系统中硬件的平均故障时间成比例地减少。我们最小化了计划重调度和抢占的比率,但由于宇宙 射线等外部因素,在如此大规模的所有硬件加速器中,真正的机器故障是司空见惯的。
文章目录 1. 准备数据集1.1 数据集存放格式1.2 config配置文件 2. 训练2.1 代码中调整了的部分2.2 训练命令 3. 评估4. 推理4.1 推理脚本4.2 推理命令4.3 推理结果4.4 特征可视化 源代码地址:Swin-Transformer
预训练模型链接:swinv2_base_patch4_window12_192_22k.pth
本机为Ubuntu系统,为了训练自己的数据集,在原代码的基础上做了一点小调整:
原代码中每个epoch保存一个模型,调整为只保存表现最佳的模型和最后一个epoch的模型原代码训练的ImageNet数据集,数据类别比较多,输出了两个评估指标:Top-1 Acc和Top-5 Acc,但我自己数据集只有3个类别,调整为输出Top-1 Acc和Top-2 Acc(其实Top-2 Acc没啥用,不输出也可以的)原代码未细化每个类别的Acc,简单补充了下该信息在终端的输出原代码没有推理脚本,简单补充了一个 1. 准备数据集 1.1 数据集存放格式 ── imagenet ├── train │ ├── class1 │ │ ├── cat0001.jpg │ │ ├── cat0002.jpg │ │ └── ... │ ├── class2 │ │ ├── dog0001.jpg │ │ ├── dog0002.jpg │ │ └── ... │ └── class3 │ ├── bird0001.jpg │ ├── bird0002.
监听回车的时候 插入BR
// 插入BR 并且移动光标
insertDomBR () { let domList = [document.createElement("BR")] const selection = window.getSelection(); let range = selection.getRangeAt(0); range.deleteContents(); let fragment = this.createElementFragment(domList); range.insertNode(fragment); selection.modify("move", "right", "character"); }, 但是(在 SAFARI 和 CHROME 中)我必须按两次“回车”键才能获得新行
这不是一个完美的破解,但它有效:它在 BR 之后添加一个空格,以便它正确显示。但是,您会发现仅添加空格“”不会改变任何内容,它适用于其他字母。浏览器不会显示它,可能是因为它就像 html 页面中的空白,它根本没有任何意义。为了消除这个错误,我创建了一个包含 标签的 div,并使用该text()属性将其放入文本节点中,否则它将无法工作。
insertDomBR () { let domList = [document.createElement("BR")] const textNode = document.createTextNode("\u00a0"); const selection = window.getSelection(); let range = selection.getRangeAt(0); range.deleteContents(); let fragment = this.createElementFragment(domList); range.insertNode(fragment); range.collapse(false); range.insertNode(textNode); range.
目录
一、大小
1、API函数
2、代码例程
二、位置
1、API函数
2、代码例程
三、对齐
1、API函数
2、代码例程
四、样式
有哪些样式属性可以设置
1、API函数
2、样式生效方式
3、代码例程
4、设置某部分的样式
5、代码例程
五、事件
1、API函数
2、代码例程
一、大小 1、API函数 设置宽度:lv_obj_set_width(obj, new_width);
设置高度:lv_obj_set_height(obj, new_height);
同时设置宽度、高度:lv_obj_set_size(obj, new_width, new_height);
2、代码例程 void my_gui(void) { lv_obj_t* obj1 = lv_obj_create(lv_scr_act()); lv_obj_set_width(obj1,20); lv_obj_set_height(obj1,30); //lv_obj_set_size(obj1, 40, 20); } 二、位置 1、API函数 设置X轴坐标:lv_obj_set_x(obj, new_x);
设置Y轴坐标:lv_obj_set_y(obj, new_y);
同时设置X、Y轴坐标:lv_obj_set_pos(obj, new_x, new_y);
2、代码例程 void my_gui(void) { lv_obj_t* obj1 = lv_obj_create(lv_scr_act()); lv_obj_set_width(obj1,20); lv_obj_set_height(obj1,30); //lv_obj_set_size(obj1, 40, 20); lv_obj_set_x(obj1,20); lv_obj_set_y(obj1,30); //lv_obj_set_pos(obj1,20,30); } 三、对齐 1、API函数 参照父对象对齐:lv_obj_set_align(obj, LV_ALIGN_.
文章目录 一、配置脚手架二、分析脚手架结构三、[render函数](https://so.csdn.net/so/search?q=render函数&spm=1001.2101.3001.7020)1.来看下main.js文件1.vue.js与vue.runtime.xxx.js的区别2.render函数是干啥的?3.为什么要引入残缺的vue呢? 四、脚手架的默认配置五、ref属性,顺便看看main.js和App.vue长啥样1.main.js3.App.vue 六、props配置项1.传递数据:2.接收数据:(1)简单接收,用的比较多(2)限制类型接收(3)限制类型、限制必要性、指定默认值 3.几个注意点4.子组件Student.vue代码 七、mixin(混入)1.第一步定义混合:2.第二步使用混合: 八、插件1.插件是干啥的?2.定义插件3.使用插件`Vue.use()` 九、scoped样式九、scoped样式 一、配置脚手架 Vue CLI(Vue Command Line Interface)Vue脚手架,Vue官方提供的标准化开发工具(开发平台)
安装node.js(安装保姆级别教程)
第一步:输入命令npm config set registry=http://registry.npm.taobao.org 配置镜像站,全局安装@vue/cil ,命令行输入npm install -g @vue/cli。命令行输入vue,不报错及安装成功
第二步:切到要创建项目的目录,然后使用命令创建项目
vue create name 然后进入新建的name项目文件目录中,输入命令:npm run serve
得到的第一个url即是你的内置服务器,第二个是同局域网的其他人可以使用
脚手架配置完毕
如果要停止工程:连按两次Ctrl+C即可。
二、分析脚手架结构 ├── node_modules ├── public │ ├── favicon.ico: 页签图标 │ └── index.html: 主页面 ├── src │ ├── assets: 存放静态资源 │ │ └── logo.png │ │── component: 存放组件 │ │ └── HelloWorld.vue │ │── App.vue: 汇总所有组件 │ │── main.
C#对象的内存布局 类:是一种类型描述,描述了这个类型有哪些数据组成,同时描述一些成员函数;
类的实例: new类();具体的内存对象,---》一块内存【int(age),int(sex), name(string)】
这块内存是所有数据成员的集合;
类的成员函数属于代码指令,编译完成以后,会编程代码指令,全局只有一份,所有的类的实例共用一份代码指令;存入到我们的代码段:编译器---代码---》.exe执行文件---》运行这个文件的时候,会把里面的所有代码加载到内存的代码段;
this实例的概念
调用这个成员函数的时候,我们会自动给成员函数,把当前的对象的实例作为this传入进去;t.test30;---> t对象实例[这块内存]---> this,通过this来操作;
类的实例:类的数据成员的所有数据(看得见得,age,4个字节, sex4个字节,string 引用类型变量(4字节), 32为系统下)
看不见得数据:编译器对齐;
组成了一个内得实例; t-->一块内存,写好代码以后编译器会定死一个偏移,age,在我对象实例里面,内存偏移多少,大小为age类型
当我们编写好一个类型以后,
(1)我们得编译器会知道每个数据的相对于对象实例内存块的偏移;
(2)我们编译器也会知道,每个类的成员函数在代码段偏移位置;-->运行的时候,就可以让指令直接跳转到这里,函数调用;
什么是反射,反射有什么作用; 一:什么是反射
C#编写的程序会编译成一个程序集(.DLL或.exe),其中会包含元数据、编译代码和资源,通过反射可以获取到程序集中的信息
程序集中包含有Microsoft 中间语言 (MSIL) 和必需的元数据。
元数据存储以下信息:
程序集的说明:标识(名称、版本、区域性、公钥)、导出的类型、该程序集所依赖的其他程序集、运行所需的安全权限。
类型的说明:名称、可见性、基类和实现的接口、成员(方法、字段、属性、事件、嵌套的类型)。
特性:修饰类型和成员的其他说明性元素。
区分 反射 与 反编译,反射读取的是元数据,反编译读取的IL代码
二:反射的优缺点
首先在编译中分为动态编译和静态编译,静态编译是在编译中确定类型,绑定对象,而动态编译是在运行中确定类型,绑定对象
反射的优点就是可以动态创建对象、绑定对象,提高了程序的灵活性和扩展性,但反射是一种解释操作,在性能上不如静态编译快
Unity游戏引擎为例,来看反射反射的作用;Unity:编辑器上挂脚本,我们给脚本初始化数据;编辑完了以后---》保存到场景文件里面;
运行的时候,我们就根据场景文件里面的内容,游戏引擎把这个节点和组件实例new出来; 上面我们描述一个类,每一个类是一种类型,都有自己独立的描述;所以我们新加一个类,就会有多的一种方式来描述;
我们办法用统一的方式来处理不同的类或类的实例;
要解决上述我们问题的本质矛盾是什么?
需要用一种方式来描述任意的类;
a:类的实例是一个内存块,内存块的大小就是这个类的所有数据成员的大小--->类的实例的内存块大小;
b:类有哪些数据成员,我可以把这些数据成员的名字,通过数组等其它方式保存起来;
数据成员数组;
{"name", type string,在对象偏移8个字节}{"age" , type int,在对象里面偏移为0个字节}{ "sex", type int,在对象里面偏移为4个字节}
c:类有哪些成员函数
"test", type成员函数(静态函数),在代码段的位置.... }{"test2", type成员函数,在代码段的位置}
{"test3", type成员函数,在代码段的位置}
定义了这样一种描述方式,我们就解决上面的问题,我们用统一的方式来描述任意不同的类型;
每个类,我们的编译器都知道数据成员的偏移,函数代码段的位置,
运行的时候,我们的C#系统会为我们每个类----》描述实例(数据内存);Type类型,Type实例,属于System名字空间;
Type:一些类型的描述信息
class FiledData {
目录
2. C++ 核心编程
2.1 程序的内存模型
2.1.1 内存四区 - 代码区
2.1.2 内存四区 - 全局区
2.1.3 内存四区 - 栈区
2.1.4 内存四区 - 堆区
2.1.5 new 运算符
2.2 C++ 中的引用
2.2.1 引用的基本语法
2.2.2 引用的注意事项
2.2.3 引用做函数参数
2.2.4 引用做函数返回值
2.2.5 引用的本质
2.2.6 常量引用
2.3 函数高级
2.3.1 函数的默认参数
2.3.2 函数的占位参数
2.3.3 函数重载 - 基本语法
2.3.4 函数重载 - 注意事项
2.4 类和对象
2.4.1 封装
2.4.1.1 封装的意义
2.4.1.2 struct 和 class的区别
2.4.1.3 成员属性设置为私有
2.4.2 对象的初始化和清理
2.4.2.1 构造函数和析构函数
利用CIC-FlowMeter工具提取流量特征 1 前言2 代码3 参数解释与执行效果3.1 参数解释3.2 执行效果 1 前言 许多研究工作基于CIC-FlowMeter工具提取的csv文件的基础上进行的,目前开源的CIC-FlowMeter工具要么使用jdk编译,要么是给出一个exe可执行文件然后使用图形化界面一个一个处理pcap,在处理大量pacp文件很麻烦,如下图。
2 代码 这里基于给出的exe可执行文件,利用python脚本批量处理pcap转化为csv文件。
import os def generate_batch_csv(pcap_dir,csv_dir,cic_path): """批量将pcap转csv""" for label in os.listdir(pcap_dir): label_path = os.path.join(pcap_dir, label) csv_label_dir = os.path.join(csv_dir,label) if not os.path.exists(csv_label_dir): os.makedirs(csv_label_dir) for pcap in os.listdir(label_path): pcap_file = os.path.join(label_path,pcap) print(f"Analyzing {pcap_file}...") # 调用cfm.bat脚本对pcap文件进行分析 os.chdir(cic_path) os.system(f'call cfm.bat "{pcap_file}" "{csv_label_dir}"') print("Done.") print("完成了{}的处理".format(label)) print("所有的都处理完成") def main(): # 设置pcap和csv文件夹路径 pcap_dir = r"xxx" csv_dir = r"xx" cic_dir = r"xx" generate_batch_csv(pcap_dir,csv_dir,cic_dir) if __name__ == "
1、问题来源 给客户部署项目,又不想将源码泄露出去。要求对正式环境的包进行安全性处理,防止客户直接通过反编译工具将代码反编译出来。
2、解决方案 2.1 第一种方案 代码混淆
采用proguard-maven-plugin插件(项目多模块不推荐)
在单模块中此方案还算简单,但是现在项目一般都是多模块,一个模块依赖多个公共模块。那么使用此方案就比较麻烦,配置复杂,文档难懂,各模块之间的调用在是否混淆时极其容易出错。
2.2 第二种方案 代码加密
采用classfinal-maven-plugin插件
此方案比对上面的方案来说,就简单了许多。直接配置一个插件就可以实现源码的安全性保护。并且可以对yml、properties配置文件以及lib目录下的maven依赖进行加密处理。若想指定机器启动,支持绑定机器,项目加密后只能在特定机器运行。
ClassFinal项目源码地址
3、项目操作 只需要在启动类的pom.xml文件中加如下插件即可,需要注意的是,改插件时要放到spring-boot-maven-plugin插件后面,否则不起作用。
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <!-- 1. 加密后,方法体被清空,保留方法参数、注解等信息.主要兼容swagger文档注解扫描 2. 方法体被清空后,反编译只能看到方法名和注解,看不到方法体的具体内容 3. 加密后的项目需要设置javaagent来启动,启动过程中解密class,完全内存解密,不留下任何解密后的文件 4. 启动加密后的jar,生成xxx-encrypted.jar,这个就是加密后的jar文件,加密后不可直接执行 5. 无密码启动方式,java -javaagent:xxx-encrypted.jar -jar xxx-encrypted.jar 6. 有密码启动方式,java -javaagent:xxx-encrypted.jar='-pwd= 密码' -jar xxx-encrypted.jar --> <groupId>net.roseboy</groupId> <artifactId>classfinal-maven-plugin</artifactId> <version>1.2.1</version> <configuration> <password>#</password><!--表示启动时不需要密码,事实上对于代码混淆来说,这个密码没什么用,它只是一个启动密码 --> <excludes>org.spring</excludes> <packages>${groupId}</packages><!-- 加密的包名,多个包用逗号分开 --> <cfgfiles>application.yml,application-dev.yml</cfgfiles><!-- 加密的配置文件,多个包用逗号分开 --> <libjars>hutool-all.jar</libjars> <!-- jar包lib下面要加密的jar依赖文件,多个包用逗号分开 --> <code>xxxx</code> <!-- 指定机器启动,机器码 --> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>classFinal</goal> </goals> </execution> </executions> </plugin> </plugins> </build> 4、启动方式 无密码启动
目录
1. excel 表格处理
(1) 读取excel 表格
(2) 抽取excel表部分列数据
(3) 保存数据到excel表格
(4) 保存到 excel 表中的不同sheet
2. 判断二维数组中的某个数值是否为空
3. 删除二维数组中的空行
4. 在列表中添加某列属性
本文是将使用pandas过程中遇到的问题进行了整理,希望可以帮到大家~
1. excel 表格处理 (1) 读取excel 表格 df = pd.read_excel("PDO.xlsx") (2) 抽取excel表部分列数据 data = df.loc[:, ["钢种", "目标厚度", "卷箱模式", "卷取结束时间"]].values (3) 保存数据到excel表格 group1.to_excel("output_rollbox.xlsx") (4) 保存到 excel 表中的不同sheet xlsx_file1 = pd.read_excel("output_rollbox.xlsx") xlsx_file2 = pd.read_excel("output_norollbox.xlsx") with pd.ExcelWriter(r'轧制节奏.xlsx') as writer: sheet1_data.to_excel(writer, sheet_name="卷箱模式") sheet2_data.to_excel(writer, sheet_name="非卷箱模式") 2. 判断二维数组中的某个数值是否为空 pd.isnull(data[i][0]) 3. 删除二维数组中的空行 np.delete(data, null_id, 0) 注:
目录
编辑
一、前言
二、概念
1、通信模型:
2、端口:
3、IP地址:
4、协议:
三、简单搭建
1、服务器代码
2、客户端代码
一、前言 Socket(套接字)是计算机网络中用于实现进程之间通信的一种机制。它提供了一种统一的编程接口,允许不同的计算机之间通过网络传输数据。套接字是网络编程的基础,它被广泛用于实现各种网络应用,包括Web浏览器、邮件客户端、文件传输等。
二、概念 1、通信模型: Socket使用客户端-服务器(Client-Server)模型,其中一个进程充当服务器,等待接受客户端的连接请求,而另一个进程充当客户端,通过网络连接到服务器。
2、端口: 在Socket通信中,端口是一个数字,用于标识一个特定的进程。端口的范围是0到65535,其中0到1023是保留端口,一般用于系统服务,而1024到65535是可用于自定义应用的端口范围。
3、IP地址: IP地址用于标识网络中的设备,分为IPv4和IPv6。IPv4地址通常以点分十进制表示,例如,127.0.0.1是本地主机地址。IPv6则使用冒号分隔的16进制表示。
4、协议: 常见的套接字通信协议有TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)。TCP提供可靠的、面向连接的通信,而UDP是无连接的、不可靠的通信,适用于一些实时性要求较高的应用。
在Socket编程中,通常有两种类型的套接字:服务器套接字和客户端套接字。服务器套接字用于监听连接请求,而客户端套接字用于发起连接请求。通过套接字,进程可以在网络上发送和接收数据,实现进程之间的通信。套接字编程通常涉及套接字的创建、绑定、监听(服务器端)、连接(客户端)、发送和接收数据等操作。 三、简单搭建 在Java中实现TCP Socket编程也是相对简单的,以下是一个简单的例子,包括服务器端和客户端的代码:
1、服务器代码 import java.io.*; import java.net.*; public class TCPServer { public static void main(String[] args) { ServerSocket serverSocket = null; try { // 创建服务器套接字,绑定端口 serverSocket = new ServerSocket(8888); System.out.println("服务器已启动,等待客户端连接..."); // 等待客户端连接 Socket clientSocket = serverSocket.accept(); System.out.println("客户端已连接,地址:" + clientSocket.getInetAddress()); // 获取输入流和输出流 BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.
参考链接;
在Ubuntu18.04下安装qemu,搭建u-boot+Linux+NFS学习环境 - 知乎 (zhihu.com)
QEM Install Sudo apt install qemu-system
xin@xin-dde:~$ qemu-system-arm -cpu help
Available CPUs:
arm1026
arm1136
arm1136-r2
arm1176
arm11mpcore
arm926
arm946
cortex-a15
cortex-a7
cortex-a8
cortex-a9
cortex-m0
cortex-m3
cortex-m33
cortex-m4
cortex-m55
cortex-m7
cortex-r5
cortex-r5f
max
pxa250
pxa255
pxa260
pxa261
pxa262
pxa270-a0
pxa270-a1
pxa270
pxa270-b0
pxa270-b1
pxa270-c0
pxa270-c5
sa1100
sa1110
ti925t
qemu-system-arm -M help
虚拟机启动脚本 qemu-system-arm -M vexpress-a9 -m 512M -nographic -dtb ./vexpress-v2p-ca9.dtb -kernel ./zImage -append “root=/dev/mmcblk0 rw console=ttyAMA0” -sd rootfs.
背景:Java项目运行时,提示端口号被占用,然后就忘记之前是怎么处理的了,感觉还是像Linux中杀掉端口号就命令行的方式比较简单一些,然后就是各种搜索,记录一下 第一步:在cmd中查看该端口号是否被占用,看下图发现有进程占用该端口号 在窗口输入 netstat -ano | findstr +需要被停止的端口(我的是8081) 第二步:杀掉占用该端口号的进程ID,我这里是9869 在窗口输入 taskkill /f /pid +进程pid,我的是9868 第三步:校验是否真正的杀掉了该端口号,看图片输出为空就对了,然后就是重新启动Java项目了 在窗口输入 netstat -ano | findstr +需要被停止的端口(我的是8081)
docker最重要的三个概念:docker镜像,docker容器,以及docker仓库。docker镜像是是docker虚拟化中最基础的部分,通过docker镜像来启动一个docker容器,docker 容器是docker虚拟化的产物。
而docker仓库是用来存储docker镜像的地方,分为公有仓库和私用仓库。默认的公共仓库,对外开放、免费或者付费使用,企业测试环境和生产环境推荐自建私有仓库。私有仓库的特点:安全、可靠、稳定、高效,可以根据自身的业务体系进行灵活升级和管理。
使用harbor做为docker仓库的优点有:
安全,可靠,性能稳定。
一、部署harbo
#安装Docker-Compose [root@localhost src]# yum install epel-release -y [root@localhost src]# yum install python-pip -y [root@localhost src]# pip install --upgrade pip [root@localhost src]# curl -L https://github.com/docker/compose/releases/download/1.18.0/run.sh > /usr/local/bin/docker-compose % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 643 100 643 0 0 1267 0 --:--:-- --:--:-- --:--:-- 1268 [root@localhost src]# chmod +x /usr/local/bin/docker-compose [root@localhost src]# ls /usr/local/bin/docker-compose /usr/local/bin/docker-compose #下载harbor 安装harbor [root@localhost src]# cd /usr/src [root@localhost src] wget -c https://storage.
基于Android(安卓)+MySQL+Tomcat开发的吃货点餐平台
项目介绍💁🏻 随着科技的发展,二十一世纪成为了以网络化、信息化为核心的社会。网络商业化也成为了时下最热门的词汇,越来越多的宅男宅女们青睐于足不出户便可处理完生活琐事。传统的订餐方式已不能满足人们的需求,为了解决这种处在高速发展社会的就餐困难的问题,所以设计了本系统。
本设计是一个基于Android手机的网上订餐系统,采用C/S模式,为客户提供网上选择、浏览菜品,在线下单服务,并为管理员提供一个服务平台实现用户信息、商家信息以及顾客订单的管理,从而提高了服务的质量。本文从系统需求、系统设计、测试等几个方面介绍了整个软件的开发过程,这个系统采用JAVA、MYSQL数据库,并利用MyEclipse、TOMCAT、Android SDK、ADT等开发环境并遵照MVC模式来进行开发。
采用MVC模式,使用TOMCAT服务器,基于Eclipse的开发平台,运用JAVA和Android语言设计并完善了基于android的手机订餐系统,实现了它的网上订餐的主要功能,且此系统界面美观、操作便捷将会受到广大用户的青睐
功能模块 本设计主要包含Android客户端和服务端的功能模块。在Android客户端,首先设计了登陆注册界面以及与服务器端的连接方式,用户可以通过此界面进行账号的登陆和注册。其次,设计了菜谱大全界面,用户可以在此查看各种菜谱信息。再次,设计了在线选择座位下单界面,用户可以在此选择座位并下单。最后,设计了我的订单界面,用户可以在此查看自己的订单信息。
在服务端,首先设计了与数据库的链接,通过此链接可以获取到数据库中的各种数据。其次,设计了Web Service服务器端,包括登陆界面、菜谱管理界面、商家管理界面、用户管理界面、订单管理界面和分组管理界面。用户可以通过这些界面进行各种操作,如登陆、管理菜谱、商家、用户、订单和分组等。通过这样的设计,可以实现用户与服务端的交互,提高系统的可用性和用户体验。
页面效果 系统的部分功能模块页面如下所示。该项目运行尽量用JDK6+Tomcat6来进行运行会更快一些
设置UTF-8不然会出现乱码
移动端登录
移动端注册
移动端登录成功
菜单详情
选座位下单
菜谱管理
添加菜谱
商家管理
用户管理
订单管理
运行教程 编号411-基于Android的智能点餐系统
系统源码 进入公众号,在右上角有放大镜,就是搜索公众号内全部文章的题目,公众号各类的素材和相关的题目都可以通过这个方法来进行搜索。
输入要自己想要看的题材和对应的素材就可以了,因为的将各个类目的题材,都浓缩在题目里面, 所以只要是标题里面有的,或者涵盖了你的题目素材基本上都可以搜索的到。
关注微信公众号 “letcoding”---》源缘编程
摘要:string类的模拟实现【设计思路+代码示例】;string类底层设计的补充说明【sizeof(string),string类设计上的效率问题:深拷贝的浪费】;扩展【写时拷贝】
1. 创建命名空间 目的:为了和 std 中的 string 区分。
namespace Bottle { class string { public: private: char* _str; size_t _size; size_t _capacity; static size_t npos; }; size_t string::npos = -1; } 2. Constructor 无参的:_str(new char[1] {'\0'}) 这里用 new char[1] {'\0'} 而不是 new char('\0') 是为了和析构函数中的 delete[] 匹配使用。全缺省的:参数缺省值 → const char* str = "" 空字符串(不含空格) —— 缺省值给空字符串同样默认以 '\0' 字符串结尾,如果这里缺省值给 "\0" 字符串会有两个 '\0' 字符,结尾默认跟 '\0'。 注意:capacity 不算结尾的 '\0' ,但开空间要预留 '\0' 的位置。
示例: //Constructor string()//无参的构造函数 :_str(new char[1] {'\0'}) , _size(0) , _capacity(0) { } string(const char* str = "
文章目录 一、适用情况示例二、SVN中文件左下角图标消失的解决步骤1. 图标消失的原因2.打开注册表3.svn相关设置4.重启生效 一、适用情况示例 SVN 下载:
如下图,左侧绿/红色图标没出来:
二、SVN中文件左下角图标消失的解决步骤 1. 图标消失的原因 因为WindowsExporerShell所支持的Overlay Icon最多十五个,当前面十五个被其他软件或者windows系统自身占用,svn就被顶掉从而无法使用,结果就是图标消失。解决方法就是 将注册表中svn图标重命名,使其在前十五个中。
2.打开注册表 按住Win+R键,输入regedit 进入注册表编辑器,按路径打开:
计算机->HKEY_LOCAL_MACHINE->SOFTWARE->Microsoft->Windows->CurrentVersion->Explorer->ShellIconOverlayIdentifiers
以Tortoise开头的都是svn图标的注册信息,只需要右键,重命名这些名称,在名称前加一个 0 就可以,名称前的空格数要与其他软件的空格数相同或者更多,这样才能保证svn图标的注册信息在最前面(重命名完后可以退出注册表重新进入检查,如果svn注册信息在最前面就可以了)
3.svn相关设置 右键svn库,TortoiseSVN->设置,然后对图标集和覆盖程序进行如下设置:
可以保持如上相同,图标集也可以选择自己喜欢的
4.重启生效 直接 重启电脑 即可
(看正点原子的教程没有看懂,这周换成江协科技的视频重新学)
一、中断基本知识
中断:在主程序的运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完后又返回原来被暂停的位置继续运行;
中断优先级:当有多个中断源同时申请中断时,中CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源;
中断嵌套:当一个中断源正在进行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回。
二、旋转编码器介绍
用来测量位置、速度或旋转方向的装置,当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向。
一般编码器有A、B、C三个输出通道,其中A、B两相输出正交信号,相位差为90°,C相输出零脉冲信号,用于标识位置。当编码器正转时,A相的输出信号超前B相90°;当编码器反转时,A相滞后B相90°。我们在程序中可以根据A、B两相信号输出的先后顺序,来判断旋转编码器是正转还是反转。但在实际实验过程中,旋转编码器输出的波形会存在抖动,需要进行消抖。
三、检测思路
1、在原代码中断服务函数的转动判断里,加一个很短的延时来实现消抖。但是我们一般不在中断函数里加延时,因为延时会占用CPU,对中断造成影响。这种方法虽然能解决抖动问题,但在编码器转动比较快时,容易漏判,不建议使用该方法。
2、A相下降沿触发中断,在A相低电平期间死循环,直到A相恢复高电平后循环结束,然后通过检测B相在这期间产生了上升沿还是下降沿来判断正、反转。判断B相是上升沿还是下降沿的方法为:每次进入中断后立即保存B相的上一个状态(Last_status),同时在A相低电平期间更新B相的当前状态(Current_status),若上一个状态是高电平,而当前状态是低电平,则为下降沿;若上一个状态是低电平,而当前状态是高电平,则为上升沿。
3、增加判断正、反转的条件,读取一个周期内的电平变化再进行判断。首先将最小系统板的PB0引脚与A相连接,触发方式选择上升/下降沿触发,用A相的输出信号来触发中断,然后在A相下降沿触发第一次中断后读取B相电平,紧接着A相上升沿触发第二次中断后读取B相电平,结合两次读取到的电平来判断是正转还是反转,这种检测方法和第二种方法的原理相同,即从A相的下降沿触发到上升沿触发期间,若B相电平发生了变化,则判定编码器转动,反之未转动,波形抖动时B相的电平保持不变,能够实现消抖。
4、STM32有一个专门的编码器接口,定时器开启编码器模式,调用标准库中的TIM_EncoderInterfaceConfig()编码器函数进行参数的配置,然后通过TIM_GetCounter()函数直接读取计数值即可。编码器模式下计数器的计数方式如下图所示,有三种模式可选择。例如:第一种模式中,当TI1FP1为上升沿(Rising)时,若TI2FP2为高电平,则计数器向下计数,若TI2FP2为低电平,则计数器向上计数;而当TI1FP1为下降沿(Falling)时,若TI2FP2为高电平,则计数器向上计数,若TI2FP2为低电平,则计数器向下计数;TI2FP2的边沿触发不计数。这种计数方式下,毛刺信号的下降沿和上升沿产生的误判之间能够相互抵消。
引脚连接: 旋转编码器最小系统板VCC3.3VGNDGNDAPB0BPB1CGND 四、编程思路
1、配置RCC,打开时钟;
2、配置GPIO;
GPIO_PinLockConfig() 函数用以锁定GPIO配置,防止意外更改 3、配置AFIO(嵌套中断向量控制器);
GPIO_AFIODeInit() 函数用于复位AFIO外设
GPIO_EventOutputConfig() 和GPIO_EventOutputCmd() 函数用于配置事件输出功能 GPIO_PinRemapconfig() 函数进行用于引脚的重映射
4、配置EXTI(外部中断),选择边沿触发方式和触发响应方式;
GPIO_EXTILineConfig() 配置AFIO的数据选择器来选择中断引脚
EXTI_DeInit() 清除EXTI配置,恢复或上电默认状态
EXTI_Init() 配置EXTI外设
EXTI_StructInit() 把参数传递的结构体配一个默认值
5、配置NVIC,选择合适的优先级。
五、cubemx配置定时器的旋转编码器模式
目标效果:顺时针旋转编码器计数值+1,逆时针旋转编码器计数值-1
1.配置时钟:外部高速时钟源HSE
2.配置引脚为外部中断模式:选择中断模式触发下降沿有效,默认上拉输入,使能NVIC
3.配置定时器,选择编码器模式,分频值为2-1,计数值为1,自动重装在值1,自动重载使能,通道1、2都计数且都是上升沿有效
4.配置时钟到72MHz,生成工程文件
5.修改定时器代码
/* USER CODE BEGIN Private defines */ typedef struct { int Encoder_Val; /*编码器计数值*/ int Encoder_Dir; /*编码器旋转方向*/ }EC11_t; extern EC11_t EC11; /* USER CODE END Private defines */ /* USER CODE BEGIN 0 */ EC11_t EC11; /* USER CODE END 0 */ /* USER CODE BEGIN 1 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { uint8_t dir = 0; if(htim == &htim3) { dir = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3); if(dir==1) { EC11.
在使用 JMeter 进行性能测试时,如果并发数比较大(比如项目需要支持 10000 并发),单台电脑(CPU 和内存)可能无法支持, 这时可以使用 JMeter 提供的分布式测试的功能,使用多台测试机一起来模拟以达到要求的负载量。
分布式测试时通常由 1 台控制机(Controller)和 N 台代理机(Agent)。控制机(Controller):负责给代理机分发测试任务,接收代理机返回的测试结果数据,做汇总展示。代理机(Agent):通过命令行模式执行控制机发送过来的脚本(不需要启动 Jmeter 界面),执行完成后将测试结果回传给控制机。 代理机(Agent)配置 步骤如下:
Agent 机上需要安装 JMeter
修改服务端口
注意:该步骤非必须。如果是在同一台机器上演示需要使用不同的端口,则可以不修改。
打开 bin/jmeter.properties 文件, 修改server_port,比如:server_port=2001
将 RMI SSL 设置为禁用 打开 bin/jmeter.properties 文件, 修改为:server.rmi.ssl.disable=true
运行 Agent 上的 jmeter-server.bat 文件, 启动 JMeter 控制机(Controller)配置 修改 JMeter 的 bin 目录下 jmeter.properties 配置文件中的remote_hosts配置项
示例:remote_hosts=192.168.182.100:1099,192.168.182.101:1099IP 和 Port 指的是 Agent 机的,多台 Agent 之间用逗号隔开 将 RMI SSL 设置为禁用:打开 bin/jmeter.properties 文件, 修改为:server.rmi.ssl.disable=true
启动 JMeter
选择菜单:运行 ——> 远程启动/远程全部启动
目标 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比5. BEVFormerv2总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》,链接。记录下个人学习笔记,仅供自己参考
本次课程我们来学习下课程第四章——基于环视Camera的BEV感知算法,一起去学习下 BEVFormer 感知算法
课程大纲可以看下面的思维导图
0. 简述 今天我们来给大家分享一下一个在 BEV 感知算法里面算是比较基础也是比较具有开创性的一个工作叫 BEVFormer
论文方面的讲解流程我们还是按照算法动机&开创性思路、主体结构、损失函数然后一些性能对比,未来展望这些方面去展开。我们这节课程还是围绕 BEVFormer 的框架来进行讲解,后续会有一节单独的课程会给大家详细讲解一下 BEVFormer 有关代码方面的一些问题,包括环境配置、模块化的一些流程以及后续的训练等方面的讲解,会在一个额外的课程上面去给大家做单独的一个说明
那下面我们就正式开始 BEVFormer 的讲解
1. 算法动机&开创性思路 论文题目其实是很能概括出作者的一个中心思想的,所以我们从题目入手,题目如下所示:
文章题目叫 BEVFormer,我们把它拆分来看前面是 BEV 后面其实是 Former,那对于 BEV 这一块我们其实已经讲过很多次了,所谓的 BEV 其实是鸟瞰图也就是俯视图。那 Former 是什么呢,我们在 CV 这个领域当中我们所讲的很多的 Former 它其实就是一个 Transformer 的结构
OK,那除了 BEV 和 Transformer 这两个内容之外题目还给了我们其他什么信息呢,那首先它提供了一个了从哪学 BEV 的一个信息,从哪学 BEV 呢,从 Multi-Camera Images 多视角图像当中去学 BEV,反过来它告诉我们什么呢,它提示我们它这个 BEVFormer 是基于 Multi-Camera 图像输入的,通过什么样的架构去提这个 BEV 呢,他提出了一个 Transformer 的一个架构,此外有一个形容词 Spatiotemporal 来修饰这个 Transformer,那 Spatiotemporal 又是什么意思呢,是一个空间上时序上的一个界定
目录 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》,链接。记录下个人学习笔记,仅供自己参考
本次课程我们来学习下课程第四章——基于环视Camera的BEV感知算法,一起去学习下 DETR3D 感知算法
课程大纲可以看下面的思维导图
0. 简述 从 4.4 节开始我们会对纯视觉感知算法进行详细的介绍,本节内容和大家一起学习一下一篇非常火的工作叫 DETR3D,我们还是围绕以下四个方面展开包括算法动机&开创性思路、主体结构、损失函数和性能对比
首先从算法动机开始
1. 算法动机&开创性思路 我们在开始之前先复习一下 BEV 感知算法设计的核心是什么呢,是视角转换模块,那有哪些视角转换方法呢,一种是我们讲的从 2D 到 3D 到 BEV 的方案,如下图所示:
2D 图像中的每个像素点可以理解成世界空间中某个点所发出的一条射线,那仅用图像不能确定此像素具体来自于射线上的哪个位置,也就是说我们不知道像素的深度值,所以从 2D 到 3D 视角转换的第一步是尝试恢复 深度信息,具体是怎么做呢,其实是为每个像素生成所有可能深度分布的一系列概率位置,在每一个位置去做一个特征,那这个特征是一个加权特征,比如某一个像素点映射在某个深度的概率可能偏高一点,那这个特征它基本就是像素的原始特征,比如投影到另一个深度的概率偏低一点,那我们这个特征乘上权重之后它就不太明显了。所有像素都投影完之后就是用原始 2D 像素特征对 3D 空间去进行的重构,那相比于特征点赋予单一的深度值,采用所有可能深度的好处在于可以提高鲁棒性,它在一些深度具有歧义的像素点上就表现得更好
那我们也讲过另外一种从 2D 到 3D 的转换方法是通过预测的深度图,如下图所示:
上图中的 Depth Map 就是我们预测的深度图,那这个深度是为每一个像素赋予单一的深度值,是确定性深度,每个像素对应映射到 3D 空间呢,那就是一一对应的关系,可以生成一系列的伪点云,那自然可以通过 3D 网络进行处理,那这种深度分布与我们上面讲的离散深度分布不同,它属于连续深度分布
OK,以上其实都是从 2D 空间出发,2D 图像上面每个像素点映射到 3D 空间,那也就是说我这个像素放到这个位置,那个像素放到那个位置,所有像素都放完之后,3D 空间其实就是用 2D 图像特征进行了重构性的表征,那这个方向我们要明白是从 2D 到 3D 的方向。
那 DETR3D 考虑的是什么问题呢,它其实不是从 2D 图像中出发而是从 3D 的 Object Query 出发再投影到 2D 图像上去取特征,那也就是说物体要什么我们拿什么,而不是把所有的 2D 图像像素特征都投影到 3D 平面上,有一些表述中把这种方式称为 top-down 或者 top-bottom 的方法,那相比于 2D 到 3D 的方法它们有什么区别呢,其实是少了深度预测模型的,无论是深度分布预测还是深度图预测 DETR3D 里面是不需要这个额外模块的,所以它自然就少引入了一点复合误差
目录 前言0. 简述1. 环视背景介绍2. 环视思路3. 主流基于环视Camera的算法详解总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》,链接。记录下个人学习笔记,仅供自己参考
本次课程我们来学习下课程第四章——基于环视Camera的BEV感知算法,先来了解下环视的背景
课程大纲可以看下面的思维导图
0. 简述 从我们第四章开始我们会对环视 BEV 感知算法去进行详细的讲解,那环视背景我们主要分为三个模块,4.1 到 4.3 节是主要针对背景介绍,第一个是环视背景,我们为什么要做环视,环视有什么优势;另外一个是对环视思路的一个讲解;另外第三个是我们本次课程当中涉及到的一些环视 Camera 算法的讲解
1. 环视背景介绍 OK,我们先看一下环视是什么,我们说的 BEV 环视,环视是什么,那我们在讨论环视之前,先来了解一下为什么需要摄像头?
与其他传感器相比,相机具有最密集的信息,所以说信息非常密集非常丰富那从中提取到信息也是非常具有挑战性的一件事情,但同时它的信息也是非常有用的,那所以我们要用环视的相机的设置来去做我们自动驾驶任务。另外一个是成本的考虑,与其他的利用激光雷达的传感器相比,相机也是很便宜的,而且相机在探测长距离物体方面它的性能往往表现是比较好的,那提取完环视信息之后可以做一些视觉的任务,比如像道路探索,比如像交通灯的状态,行车标志等等,像这些东西是需要视觉去感知的,像普通的激光雷达是很难做到这些事情的
那我们知道我们说的环视是一种环绕摄像头的设置,那摄像头的数量可能会因为不同的自动驾驶公司产生一点点的区别,通常情况下来讲每辆车一般是 6-12 个摄像头,可能需要这些多个相机覆盖车辆周围的 3D 场景,那如果只有单一相机会出现什么问题呢,比如我们可能只有前视角的图像,那前视角的数据是一个比较局限的数据,如果利用单一视角的数据去做后续的一系列的感知任务的话,那对我们的安全性是具有严重的挑战的
那另外一个我们再看一个事情,我们说的环视传感器是我们相机的本身硬件带来的优势,那环视为什么要做 BEV 呢?那俯视空间跟环视传感器是什么关系呢?鸟瞰图其实是非常适合环视的一种特征表达方式,我们在鸟瞰图中使用 3D,为什么呢,因为它与 360° 的传感器融合会很自然
我们举个简单例子,比如像 LiDAR,比如像 Radar,我们在多视角场景下怎么样把这个多视角的数据统一到一个特征空间上面去做融合判断呢,哪个空间很适合做这个事情呢,俯视空间很适合做这个事情,BEV 当中操作可以很好的模拟动态场景的时间一致性,与普通的透视视图相比,透视视图就是所谓的相机视角,BEV 中的运动补偿就是平移,还有旋转的建模,是要简单很多的。
那比如在 BEV 视图当中车辆自身的这个姿态变化取决于运动,那我们如果在透视视图当中,普通的相机视角下如果车辆自身发生变化的话,它的姿态变化取决于什么呢,取决于深度和运动,所以说在 BEV 空间当中考虑车辆的姿态变化是一个相对简单的事情。另外一个在 BEV 视图当中我们也讲过目标是具有尺度一致性的,而透视图不是比如前视图物体离我们前视图越近,它看起来越大,离我们相机视角越远看起来越小,那所以透视图具有尺度变化差异,同一个物体可能产生特征上的差异性,那这就给我们后续的检测会带来一些困难
然而 BEV 视图不是,BEV 视图下同类目标尺度差异我们可以认为近似没有,小轿车应该都差不多大,它的差异也只是微小差异,所以我们说 BEV 视图学习特征尺度一致性会变得更加容易
那如果构造出一个比较好的 BEV 空间的话对后续的下游任务也是更好的,后续下游任务有哪些呢,比如说像运动预测,运动规划,那在 BEV 视图下有一个通用坐标系去处理这个事情,那所以我们说环视的优势就在于它可以利用 360° 的相机数据来看我们的 3D 场景,那 BEV 环视的优势呢,是将多视角数据可以统一的融合到 BEV 视角下去做后续一系列的处理任务,那它难点在哪呢,难点就是我们怎么把环视数据统一的都能映射到 BEV 空间上面,那这是任务的难点。
目录 前言1. BEVFusion实战 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》,链接。记录下个人学习笔记,仅供自己参考
本次课程我们来学习下课程第三章——LiDAR和Camera融合的BEV感知算法,一起去学习下 BEVFusion 的相关代码
课程大纲可看下面的思维导图
1. BEVFusion实战 实战部分先放放吧,感兴趣的可以点击 here 自行学习
To be continue…
目录 前言0. 简述1. 算法动机&开创性思路2. 主体结构2.1 相机支路2.2 点云支路2.3 Fusion 3. 损失函数4. 性能对比总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》,链接。记录下个人学习笔记,仅供自己参考
本次课程我们来学习下课程第三章——LiDAR和Camera融合的BEV感知算法,一起去学习下 BEVFusion 感知算法
课程大纲可看下面的思维导图
0. 简述 本次课程来给大家讲解一篇非常经典的融合工作叫 BEVFusion,我们依旧从算法动机&开创性思路、主体结构、损失函数以及性能对比四个方面展开
BEVFusion 有两篇文章,本次课程主要讲解的是阿里和北大的:BEVFusion: A Simple and Robust LiDAR-Camera Fusion Framework
另外一篇是 MIT 的工作:BEVFusion: Multi-Task Multi-Sensor Fusion with Unified Bird’s-Eye View Representation
1. 算法动机&开创性思路 我们先看 BEVFusion 这个名字能想到什么呢?很显然,我们将它拆开来看,一个是 BEV,另一个是 Fusion
那 BEV 是什么呢?是一个俯视空间,鸟瞰图,我们称之为上帝视角
那什么叫 Fusion 呢?翻译过来叫融合,那既然是融合是什么和什么的融合呢?通常情况下我们讲的融合是跨模态的融合,比如图像和语音信号的融合,图像和毫米波雷达的融合,图像和激光雷达点云的融合。
BEVFusion 属于哪种如何呢?从下面的框图中我们也能够看出来它属于图像和点云的融合
图1 BEVFusion整体结构 融合的输入知道了,那是怎么做融合的呢?那也就是说我们怎么把图像和点云融合在一起的呢?
作者认为融合方法可以分为三种,如下图所示:
图2 LiDAR-Camera融合方法对比 第一种叫做 Point-lever Fusion 也就是点级的融合,Point-level 中的 Point 指的是点云中的点,那也就是说 Point-lever 的策略是从点出发,从点云中采样出一些点,然后我们根据相机的内参和外参矩阵将采样的点投影到图像上采样出图像特征,然后再拼接到点云上。我们在 (a) 中能看到橙色 ■ 部分和蓝色 ■ 部分是对应的点特征和图像特征,我们会利用融合后的特征去做 3D 检测,这就是点级的融合。
目录 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》,链接。记录下个人学习笔记,仅供自己参考。
本次课程我们来学习下课程第三章——LiDAR和Camera融合的BEV感知算法,一起去学习下 BEV-SAN 感知算法
课程大纲可看下面的思维导图
0. 简述 本次课程给大家介绍一个比较新的融合感知工作,叫 BEV-SAN,其中 S 代表 Slice 切片的意思,A 代表 Attention 注意力的意思,N 代表 Network 网络的意思,所以我们知道它是用来干啥的呢,BEV 空间,要做什么呢,做 Slice Attention 切片注意力,我们从题目中能看出这么多信息
OK,我们依旧从算法动机&开创性思路、主体结构、损失函数以及性能对比四个方面展开
1. 算法动机&开创性思路 先简单看一下,我们在说 BEV-SAN 的算法动机之前,BEV 算法有哪些组成部分呢,已有的 BEV 检测方法主要包括以下三个模块:
RGB/LiDAR 特征提取模块BEV 特征构造模块检测头模块 其中的特征提取模块其实与我们输入有关系,比如说我们输入的是纯视觉的方案,我们只有图像级的输入,那我们后续特征提取自然也就只有图像特征提取网络,如果有 LiDAR 的输入,有点云的输入,那我们自然会有点云特征提取网络,如果我们两个都有,那我们网络会既需要图像特征提取模块,也需要点云特征提取模块
有了特征提取模块之后会得到什么,我们得到特征,图像输入到图像处理模块得到图像特征,点云输入到点云处理模块我们得到点云特征,有了图像或点云特征怎么样去生成要的 BEV 表征呢,后续第二个很重要的模块是如何利用前面提取到的特征得到 BEV 表征,也就是 BEV 特征构造模块
有了 BEV 特征之后,比如已经生成好了一个比较好的 BEV 表征,我们基于 BEV 表征可以连一个检测头在 BEV 空间上做检测
那以上三个模块其实就是 BEV 算法通用的组成部分,区别就是每个模块大家可能使用不同的框架,不同的网络去干同样的一件事情,那比如 BEVFormer 当中使用 SpatialTemporal 去学习一个统一的 BEV 空间表征方式,我们今天要讲的 BEV-SAN 这篇文章也是针对于 BEV 特征构造模块的一篇工作,我们怎样能比较好的构造 BEV 特征,我们直接拍扁是一种好的方式吗,那这就是 BEV-SAN 要考虑的一个问题
目录 前言0. 简述1. 融合背景2. 融合思路3. 融合性能优劣总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》,链接。记录下个人学习笔记,仅供自己参考
本次课程我们来学习下课程第三章——LiDAR和Camera融合的BEV感知算法,先来了解下融合的基本概念
课程大纲可以看下面的思维导图
0. 简述 从第三章开始我们会针对详细的算法来给大家进行一个讲解
那我们在第三章当中主要针对融合算法也就是 LiDAR 和 Camera 融合感知的方案
我们在第四章当中主要是针对纯视觉的方案,也就是仅仅依赖单一的多视角图像输入的方法做 BEV 感知
我们开始第三章融合算法的基本介绍,我们主要分为三块内容,融合背景介绍,融合思路介绍以及融合的性能评价
1. 融合背景 我们先简单介绍一下融合的背景,第一章中提到过 BEV 感知是建立在多个子任务上的一个概念,这些子任务包括分类、检测、跟踪、分割等等,所以说我们的 BEV 是一个比较综合性的概念,它的输入也是比较宽泛的,包括毫米波雷达的输入,激光雷达点云的输入,视觉系统的输入,还有 GPS,轨迹等等,那我们得到的结果是可以为后续的决策规划提供一个比较好的支撑的
根据输入的不同,我们可以把 BEV 感知算法进行一个分类,这个分类是比较清晰的,以相机图像为输入的算法我们叫 BEV-Camera,具有代表性的有 BEVFormer、BEVDet 系列,以单点云为输入的算法我们称之为 BEV-LiDAR,那这部分其实是与传统的纯点云的方法一样,比如 PV-RCNN、PV-RCNN++ 等等,以图像和点云混合输入的方法我们称之为融合感知的方法,像 BEV-Fusion,像这类方法是同时处理图像和点云特征的,会生成一个 BEV 的多模态的表征,像这类方法中很具有代表性的就是 BEVFusion
那以上其实是一个融合背景的简介,我们知道要做融合之后,我们思考第一个问题,为什么要做融合?我们希望融合可以达成怎样的一个目的呢?🤔
实际上我们希望融合是可以实现一个模态信息的互补,那什么叫互补呢,你没有的我有或者你有的我没有,我们俩能够实现 “1+1>2”,我们称这就叫互补。那我们希望实现多模态信息的互补,这也就意味着单模态是有无法避免的一个劣势的,单模态数据的感知是存在一个固有的缺陷
我们先说相机数据,相机数据主要是在前视图一个比较低的位置捕获的,大家在上图中也能看到,其实是一个偏平视的结果,相机模态存在的一个问题是复杂场景遮挡问题,会造成视觉表征的一个丢失。同样,激光雷达数据也是存在固有缺陷的,它受限于机械结构,在不同的距离具有不同的分辨率,这也就意味着我们采样点的数目是随着距离而变化的,而且激光雷达也很容易受到雨天、雾天等极端天气的影响。
所以说目前的单一模态都有固有的缺陷,我们当然希望通过多模态融合的方式实现跨模态信息的互补。从未来的角度出发,相机信息和点云信息的互补可以使得自动驾驶在感知层面上变得更加安全,我们这里讨论的主要任务还是 3D 检测和 3D 分割任务。
我们讲的多模态融合的输入输出是什么呢,输入自然是跨模态的数据,比如图中的点云和图像,输出则是感知结果,而感知结果是与任务相关的,它可以做一系列的任务,比如 2D 检测,3D 检测,2D 分割,3D 分割等等
那融合在哪做呢,怎么样把输入数据进行融合得到我们最终的结果呢,下面我们来逐步分析
2. 融合思路 一般而言融合方案其实是有三种划分的:
前融合(数据级融合)指通过空间对齐直接融合不同模态的原始传感器数据深度融合(特征级融合)指通过级联或者元素相乘在特征空间中融合跨模态数据后融合(目标级融合)指将各模态模型的预测结果进行融合,做出最终决策 第一种方法叫前融合即数据级融合,也叫 pre-fusion,它通过一种空间对齐的方式直接融合不同模态的原始数据,比如说点云是可以投影到 2D 空间当中的,会生成一个伪 2D 图,那这是不是一种数据融合的方式,或者说我们如果有图像的深度数据,图像的像素数据按照深度值可以投影到 3D 空间,可以生成一系列的伪点云,从图像能到点云,后续我们可以把图像数据按照伪点云的方式处理,那这也是一种数据级的融合方式
一.函数指针 1.1函数的定义 在讨论函数指针的定义之前,我们同样先看函数是怎么样定义的:
如上图所示,函数是由三个部分组成,分别为
函数名 + ( ) (括号证明这是一个函数)函数参数 int x和int y函数的返回类型 int 而调用函数时需要函数名+ (对应的参数)即可,如上图的Add(a,b)
1.2函数指针的定义 函数指针说白了也是一个指针,指针中所保存的地址中的内容是一个函数,同之前说过的数组指针相似,函数指针的定义便是
返回类型 (* 指针名) (函数参数) //例如: int (*pa) (intx,iny)
同数组指针一样,当定义函数指针的时候,* 需要和指针名打括号相结合,( )的优先级高于 * ,不打括号编译器自动会将 指针名 与( )相结合,如 int * pa (int x,int y) ,这样的话便是一个名为pa的函数,函数参数为 int x,int y,函数的返回类型时 int *
1.3示例 示例1:
(*(void (*)())0)(); 请问:该代码是什么意思? 分析:我们先将左右两边的括号一个一个匹配,变成如下:
相同颜色为一组括号 然后再从内到外逐层拆解
先看 void ( * ) ( ) ,这是一个标准的函数指针,函数返回类型为void,无函数参数再看蓝色括号,该括号的代表强制转换,例如:(float)3 指的是将int类型的3转换为float类型,在这里指的是将int类型的0转换为函数指针类型看蓝色括号前面的 * ,这里是解地址符,指找到地址是0的函数红色的括号包括着地址是0的这个函数(函数指针此时是0),后面再跟着一个绿色的括号,相当于调用函数 所以该代码是一次函数调用,调用的是一个返回类型为void,无函数参数,函数名为0 的一个函数
1.3函数指针的调用 我们先来看一个有意思的情况:
如上图,当尝试打印Add函数的地址和Add这个函数变量名时,会发现Add变量名就是函数的地址,相当于我们平时在调用函数时就是在通过类似指针调用
BeanFactory是什么? BeanFactory是Spring 容器的根接口,它是IOC的基本容器,负责管理和加载Bean,它为具体的IOC容器提供了最基本的规范,比如DefaultListableBeanFactory和ConfigurableBeanFactory,BeanFactory也提供了用于读取XML配置文件的实现,比如XMLBeanFactory。
ApplicationContext接口是BeanFactory的扩展,它除了具备BeanFactory接口所拥有的全部功能外,还有应用程序上下文的一层含义,主要包括:
继承自ListableBeanFactory接口,可以访问Bean工程上下文的组件继承自ResourceLoader接口,以通用的方式加载文件资源继承自ApplicationContextPublisher接口,拥有发布事件、注册监听的能力继承自MessageResource接口,解析消息,支持国际化 它最主要的实现就是ClassPathXmlApplicationContext,用来读取XML配置文件。
FactoryBean是什么? FactoryBean是一个接口,它本身就是一个对象工厂,如果Bean实现了该接口,它被用作公开的对象工厂,而不是作为直接将bean暴露的实例,该接口在框架内部大量使用,例如AOPProxyFactoryBean和JndiObjectFactoryBean,也可以自定义组件,
Spring Boot 官方不再支持 Spring Boot 的 2.x 版本了,之后全力维护 3.x;而 Spring Boot 3.x 对 JDK 版本的最低要求是 17,所以在IDEA创建SpringBoot项目, Spring Initializr时没有JDK 8版本
解决方法:
不使用官方提供的 Spring Initializr 来初始化项目,使用阿里云提供的脚手架镜像(https://start.aliyun.com/)创建SpringBoot项目
IDEA创建项目时,SpringInitializr里更改 Server URL为:https://start.aliyun.com/
下面选择JDK版本就会出现JDK 8,选择后创建即可
🚩write in front🚩 🔎 介绍:"謓泽"正在路上朝着"攻城狮"方向"前进四" 🔎🏅 荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评百大博主、华为云享专家、阿里云专家博主、掘金优秀创作者、全网粉丝量7w+、个人社区人数累计4w+、全网访问量100w+🏅🆔 本文章内容由 謓泽 原创 如需相关转载请提前告知博主 ⚠📑 创作时间:2023 年 12 月 10 日 📅📝 个人主页:謓泽的博客 📃📣 专栏系列:【电子】系列_謓泽的博客📃🙌 Gitee:謓泽 (wsxsx) - Gitee.com ⭐️🎁 点赞👍+ 收藏⭐️+ 留言📝 ✉️ 我们并非登上我们所选择的舞台,演出并非我们所选择的剧本 📩
1.开关 一、开关接相线,暗装,落地插座有盖板。 相线即火线(L) 二、万能触电、行程反力。
三、铁壳开关2倍;组合开关2~3倍。
四、同型号同高度;微行程有储能。
五、28KW以下用铁壳;10KW以下用组合、胶壳。
2.电流表 🐟 电压表 一、不能带电换量程。
二、直流电流表电压表测平均值,交流电流表电压测有效值。
三、内阻:电压表选择大、电流表选择小。(压大流小)
四、串等流、并等压。
五、电流与电压成正比,电流与电阻成反比。
3.磁电式、电磁式、电动式 一、磁电看磁铁;电磁看铁芯;电动两线圈;
二、磁低动高(电磁精度低;电动精度高)
三、磁电式,测直流,易改装。
四、直流测直流,交流测交流,钳形电流都可以测。
4.继电器 一、电压并联,电流串联。
二、看见热继电器,选温度或过载,没温度或过载全都错。
三、中间继电器,不可调节。
5.断路器 一、断路器,看脱扣,(断路器)保短路、过载和欠电压,(断路器)可分框架和塑料。
二、断路器正常工作相量和为0,自动空气开关也称为断路器。
三、民用漏电保护,(断路器)先定类型,再定参数。
6.熔断器 一、熔断电流1.1;启动电流4~7;
二、熔断器,秒动作,看电流;主要功能保短路,一般线路加过载。
三、胶壳刀开关接上端;螺旋式熔断器接下端。
四、多级熔断扩范围,电源跟在最后端。
五、一对一,排在后;新旧要相同。
六、额定电压,灭弧出发。
7.电容器 一、电容器很乖巧,能充能放还能存。
1.git下载 如果没有xshell下没有下载过git,可以参考这篇的教程:Linux配置安装 git 详细教程
下载后可以通过 git --version 查看git的版本号,验证是否安装成功
2.新建仓库 首先需要在gitee上注册一个账号
然后再主页面点击右上边框的 + 号,选择新建仓库,建立一个仓库:
然后填写新建仓库的名称,系统会根据填写的名称自动生成路径;然后填写仓库的介绍;创建的时候只能选择私有(要设置开源可以在创建成功后,再改为开源),再勾选初始化仓库、设置模板、选择分支模型,然后点击创建就可以了。
补充截图: 仓库建好后,回到个人主页,点击仓库就能看见我们自己新建的仓库。点击仓库名就能进入到仓库内部。
3.clone远程仓库 在xshell下安装远程仓库,需要先获取我们仓库的链接:选择https然后复制,进入xshell。
在xshell下输入指令:
git clone 链接 输入指令后回车,需要输入gitee的用户名和密码,需要输入正确才能clone远程仓库。
用户名是指我们个人主页上的@后面的名字,这个一般是系统自动生成。
这样我们的远程仓库就clone在xshell上了。目录的文件名就是仓库的名字 hellogit
4.git上传 git上传文件需要先将上传的文件放在xshell下对应的clone仓库的目录下:
这里以上传test.c文件为例。
git上传有三板斧:
1.
git add 要上传的文件名 2.
git commit -m "上传的文件说明" # 很重要!!! 对上传的文件一定要有说明,说明的内容用“”包含 当我们第一次上传的时候,会出现如下问题,问题的描述是需要告诉它我们上传到gitee上的用户的邮箱和用户名。
邮箱是指gitee上绑定的邮箱号、用户名就是@后面的内容:
这时只需要输入如下两条指令即可:
git config --global user.email "邮箱号" git config --global user.name "用户名" 然后再进行上传:
3.
最后的提交指令:
git push 需要再输入gitee的用户名和密码:
上传完成后,可以去gitee仓库中查看已上传的文件:
目录 概述
功能
密钥生成
基点G的生成
模数p
密钥生成过程
加解密
加密过程:
解密过程:
数字签名
概述
对第5步r的计算方式分析
对第6步s的计算方式分析
加密模式
优缺点
论文和研究方向推荐
论文
研究方向 概述 SM2是中国密码学算法标准中的一种非对称加密算法,它是由国家密码管理局(中国密码局)发布的一种椭圆曲线公钥密码算法。SM2基于椭圆曲线离散对数问题,主要用于数字签名、密钥交换和加密等密码学应用。
以下是SM2算法的主要特点和原理:
非对称加密:SM2使用非对称密钥加密体制,包括公钥和私钥。公钥用于加密数据和验证数字签名,私钥用于解密数据和生成数字签名。
椭圆曲线密码学:SM2基于椭圆曲线密码学,通过椭圆曲线上的点运算来实现加密和解密操作。SM2采用的是素数域上的椭圆曲线,具体是由国家密码管理局指定的一条256位的椭圆曲线。
安全性:SM2具有较高的安全性。它使用的椭圆曲线离散对数问题被认为是难以解决的数学难题,可以提供强大的安全性保障。同时,SM2还采用了一系列安全性增强措施,如密钥派生函数和随机数生成算法,以防止各种攻击。
数字签名:SM2可以用于生成和验证数字签名。发送方可以使用私钥对数据进行签名,接收方使用相应的公钥来验证签名的有效性。数字签名可以确保数据的完整性和身份认证,防止数据被篡改或冒充。
密钥交换:SM2还可以用于密钥交换,双方可以使用各自的私钥和对方的公钥来生成一个共享密钥,用于后续的对称加密通信。
SM2作为中国密码学标准的一部分,被广泛应用于各种信息安全领域,包括电子商务、移动支付、互联网金融等。它具有较高的安全性和性能表现,并得到了国际密码学界的认可和关注。
功能 密钥生成:
随机选择一个私钥(随机数),通常是一个256位的随机数。使用椭圆曲线上的点运算,将私钥与基点(椭圆曲线上的固定点)相乘,得到公钥。公钥是一个曲线上的点,可以表示为(x, y)坐标。 加密:
随机选择一个临时私钥(临时随机数),通常是一个256位的随机数。使用临时私钥与基点相乘,得到临时公钥。将明文数据转换为椭圆曲线上的点(编码)。生成一个随机数k,与临时公钥进行点运算,得到C1点。使用接收方的公钥进行点运算,将C1点与明文数据进行异或运算,得到C2点。使用临时私钥与C1点相乘,得到一个数值。对C2点和该数值进行哈希运算,得到C3点。将C1、C2和C3点组成密文。 解密:
使用私钥与C1点相乘,得到一个数值。对C2点和该数值进行哈希运算,得到C3点。将C1、C2和C3点组成密文。使用接收方的私钥与C1点相乘,得到临时公钥。使用临时公钥进行点运算,将C1点与C2点进行异或运算,得到明文数据。 数字签名:
对待签名数据进行哈希运算,得到哈希值。随机选择一个数值k,与基点相乘,得到点(x1, y1)。将x1的值与哈希值进行异或运算,得到一个数值。计算该数值的模反函数,得到另一个数值。将哈希值与另一个数值进行相乘,得到一个数值。使用私钥与该数值相乘,得到一个数值。使用点(x1, y1)与该数值进行点运算,得到点(x2, y2)。 将x2的值与哈希值进行比较,如果相等,则签名有效。
在SM2算法中,加密和解密是绑定在一起的,需要使用一对密钥,即公钥和私钥。发送方使用接收方的公钥进行加密,接收方使用自己的私钥进行解密。因此,加解密是作为一个整体功能进行使用的。
数字签名功能是可以独立使用的。发送方可以使用自己的私钥生成数字签名,并将签名附加在数据上发送给接收方。接收方使用发送方的公钥来验证数字签名的有效性,从而确保数据的完整性和身份认证。
密钥生成是SM2算法的前置步骤,它用于生成一对公钥和私钥。这对密钥可以用于后续的加解密和数字签名操作。因此,密钥生成是一个单独的功能,它为之后的加解密和数字签名提供了必要的密钥。
综上所述,可以将SM2的加解密作为一个绑定的功能,数字签名作为一个独立的功能,并单独考虑密钥生成作为另一个功能。
密钥生成 基点G的生成 基点G(也称为生成点、基点或基础点)是椭圆曲线上的一个特殊点,用于执行关键的操作和生成密钥对。
基点G的主要用途有两个:
密钥生成:基点G可以用作生成密钥对的基础。通过在椭圆曲线上对基点G进行重复的点运算,可以生成一系列相关的点,其中的某些点可用作公钥,另一些点可用作私钥。
密钥交换:基点G还可以用于执行密钥交换协议。参与者可以利用基点G和一些算法,通过交换计算的中间结果,最终协商出共享的密钥。
每个椭圆曲线都有一个对应的基点G(一对一的),这个基点是特定椭圆曲线上的一个固定点。基点G是椭圆曲线密码学中非常重要的组成部分,它定义了椭圆曲线上的加法运算和密钥生成过程。
通常,在设计椭圆曲线时,会选择一个合适的素数域模数p和相应的椭圆曲线方程。然后,根据特定的算法和安全要求,计算出一个合适的基点G,并确保它满足一些数学性质,如阶(order)和循环性。
一个模数p和一个椭圆曲线方程可以唯一确定一个基点G。 基点G是曲线上的一个特殊点,它需要满足一些附加条件才能成为合适的基点。这些条件包括:
在椭圆曲线上:基点G必须位于椭圆曲线上,即满足椭圆曲线方程。
有合适的阶(order):基点G的阶是指它与自身的倍数相加的结果的个数。一个好的基点应该有一个适当大的阶,以提供足够的安全性。
循环性:基点G的倍数相加应该能够遍历曲线上的所有点,不会出现重复的点。这种循环性是基于基点G的阶。
假设我们有一个椭圆曲线方程为:
E: y^2 = x^3 + ax + b
其中,a和b是曲线的系数。
简介 原型和原型链是JavaScript中与对象有关的重要概念,但是部分前端开发者却不太理解,也不清楚原型链有什么用处。其实,学过其他面对对象语言的同学应该了解,对象是由类生成的实例,类与类之间有继承的关系。在ES6之前,JavaScript中并没有class,实现类和继承的方法就是使用原型。在我个人看来,JS中类和原型链的设计和语法由于一些历史或包袱问题而不易用,也不易于理解。因此在ES6中推出了class相关的语法,和其他语言更接近,也更易用。
ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。(ECMAScript6入门教程 阮一峰)
虽然有了class,但是原型链相关的内容我们依然要掌握。不仅是因为作为前端开发者,我们要深入理解语法。而且在查看源码,以及实现一些复杂的面对对象写法时,依然是有用的。因此在这篇文章中,我们一起搞懂JavaScript中的原型和原型链。(这篇文章并不会涉及class相关语法)
构造函数与原型 构造函数 在JS中创建实例的方法是通过构造函数。在构造函数中通过this实现对实例的操控,比如赋值各种属性和方法。我们看个例子:
// Person构造函数 function PersonFun(name) { this.name = name; this.getName = function() { return this.name; } } // 创建实例 const p1 = new PersonFun('jz'); console.log(p1.name, p1.getName()); // 输出结果: // jz jz 我们创建了PersonFun构造函数,使用new关键字创建了实例p1。可以看到,在构造函数中对this增加了属性和方法,最后成为了实例的属性。注意构造方法必须使用new调用。但是这样所有的属性都是实例属性,包括那个getName方法:
const p1 = new PersonFun('jz'); const p2 = new PersonFun('jz'); console.log(p1.getName === p2.getName); // 输出结果: // false 原型对象 只用上面的构造函数,依然没有“类”的存在。这时候我们增加原型这一概念,可以理解为是实例对象的类。原型对象可以通过构造函数的prototype属性访问。
// Person构造函数 function PersonFun(name) { this.name = name; } // Person原型对象 PersonFun.
1. 非负矩阵:矩阵元素均非负 定义 7.1.1 设 A = ( a i j ) ∈ R m × n \boldsymbol{A}=\left(a_{i j}\right) \in \mathbb{R}^{m \times n} A=(aij)∈Rm×n, 如果
a i j ⩾ 0 , i = 1 , ⋯ , m ; j = 1 , ⋯ , n , a_{i j} \geqslant 0, \quad i=1, \cdots, m ; j=1, \cdots, n, aij⩾0,i=1,⋯,m;j=1,⋯,n,
即 A \boldsymbol{A} A 的所有元素是非负的, 则称 A \boldsymbol{A} A 为非负矩阵, 记作 A ⩾ 0 \boldsymbol{A} \geqslant 0 A⩾0; 若式 (7.
问题
项目中需要根据不同的版本添加不一样的 css 样式,于是在 main.js 中添加 if 条件判断,发现即使没有进入判断里,require 始终会引入。
解决方法
查阅 require.js 机制后发现,require 依赖前置,所以添加 if 限制无效。
因此需用 [ ] 将引入路径包裹起来就可以实现按需引入,如下:
if(window.THEME == 'dark'){ require(['@/assets/css/dark.scss']); };
资源 服务器名称ip地址服务master1(2C/4G,cpu核心数要求大于2)192.168.100.10docker、kubeadm、kubelet、kubectl、flannelnode01(2C/2G)192.168.100.30docker、kubeadm、kubelet、kubectl、flannelnode02(2C/2G)192.168.100.40docker、kubeadm、kubelet、kubectl、flannelnode03(2C/2G)192.168.100.50docker、kubeadm、kubelet、kubectl、flannel 1、在所有节点上安装Docker和kubeadm
2、部署Kubernetes Master
3、部署容器网络插件
4、部署 Kubernetes Node,将节点加入Kubernetes集群中
环境准备 所有节点,关闭防火墙规则,关闭selinux,关闭swap交换 systemctl stop firewalld systemctl disable firewalld setenforce 0 iptables -F swapoff -a #交换分区必须要关闭 #加载 ip_vs 模块 for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i >/dev/null 2>&1 && /sbin/modprobe $i;done 修改主机名 hostnamectl set-hostname master1 hostnamectl set-hostname node01 hostnamectl set-hostname node02 hostnamectl set-hostname node03 免密打通 ssh-keygen -t rsa cd ~/.ssh/ ssh-copy-id -i id_rsa.pub root@192.168.100.30 ssh-copy-id -i id_rsa.
报错信息:PermissionError: [Errno 13] Permission denied: 'xxx'
场景:
用openpyxl库往excel文件中写入数据、最后执行workbook.save(path)的时候报错。
解决方法:把目标文件关闭,重新执行即可。
分析过程:
在进行excel读写处理前,有通过 if os.path.exists(path) 检查文件路径,可以确定目标文件是存在的。错误原因是我把这个文件打开了,导致python无法对它进行写入操作。
延申思考:
python中的异常处理机制可以捕获到特定类型的Exception。所以我试了一下,把处理放到try模块中,当捕获到PermissionError这个类型的异常时,弹出警告框提醒使用者。
基本结构如下:
def on_Test(self): try: path = r'D:\Test\output001.xlsx' # 把excel文件的读写处理放在这里,具体内容这里忽略 except PermissionError: print("出现异常") QMessageBox.information(self, '提示', '请确认该文件已关闭!\n文件路径:'+path) else: # 没有异常时执行的处理 print("文件已成功写入") finally: # 不管是否有异常都会执行的处理 print("do nothing") on_Test()是与按钮绑定的一个事件,当用户点击按钮时,执行try中的逻辑,当捕捉到PermissionError异常,弹出MessageBox提醒用户关闭文件。结果可行。
参考文章:
解决Python报错:PermissionError: [Errno 13] Permission denied_python permission denied-CSDN博客
SpringMVC简介 MVC模型 MVC全称Model View Controller,是一种设计创建Web应用程序的模式。这三个单词分别代表Web应用程序的三个部分:
Model(模型):指数据模型。用于存储数据以及处理用户请求的业务逻辑。在Web应用中,JavaBean对象,业务模型等都属于Model。
View(视图):用于展示模型中的数据的,一般为jsp或html文件。
Controller(控制器):是应用程序中处理用户交互的部分。接受视图提出的请求,将数据交给模型处理,并将处理后的结果交给视图显示。
SpringMVC SpringMVC是一个基于MVC模式的轻量级Web框架,是Spring框架的一个模块,和Spring可以直接整合使用。SpringMVC代替了Servlet技术,它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无须实现任何接口。
SpringMVC入门案例 接下来我们编写一个SpringMVC的入门案例
使用maven创建web项目,补齐包结构。
引入相关依赖和tomcat插件
<dependencies> <!-- Spring核心模块 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.12.RELEASE</version> </dependency> <!-- SpringWeb模块 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.12.RELEASE</version> </dependency> <!-- SpringMVC模块 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.12.RELEASE</version> </dependency> <!-- Servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <!-- JSP --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <!-- tomcat插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.1</version> <configuration> <port>8080</port> <path>/</path> <uriEncoding>UTF-8</uriEncoding> <server>tomcat7</server> <systemProperties> <java.
完工,最后CB链没时间打了,估计也不怎么打得出来,今天一边在打polar一边弄服务外包赛,好累呜呜呜。
Polar 冬 干正则(WEB) 直接给了源码
parse_str():将字符串解析成多个变量
payload:
?id=a[]=www.polarctf.com&cmd=;cat%20flag* Polar 冬 upload(WEB) 开题
源码里面发现hint
得到源码如下:
$is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess"); $file_name = trim($_FILES['upload_file']['name']); $file_name = str_ireplace($deny_ext,"", $file_name); $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.rand(10000,99999).$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } } str_ireplace():替换字符串中的一些字符(不区分大小写)。双写即可绕过。
直接getshell就行。
Polar 冬 cookie欺骗(WEB) 伪造一下Cookie就行
Floyd算法求解各顶点之间最短路径问题 一、Floyd算法 一、Floyd算法 概述 Floyd算法,也称为Floyd-Warshall算法,是一种用于求解图中所有节点之间最短路径的算法。Floyd算法可以处理负权边的情况,但是不能处理负权环。
Floyd算法基于动态规划思想,通过一个二维数组记录从一个节点到另一个节点的最短路径长度。算法的核心思想是逐渐增加中间节点,如果在加入一个中间节点后能够获得更短的路径,则更新路径长度。经过n次迭代之后,最终可以得到图中任意两个节点之间的最短路径长度。
示例 初始状态 如图:这是一个有三个顶点的有向图,矩阵A存储了两点之间的最短距离,在初始状态下就是一个邻接矩阵;矩阵pre记录了两点之间的最短路径中,加入的中转顶点。
以 v 0 v_0 v0为中转点 初始状态路径长度加入中转点 v 0 v_0 v0路径长度是否加入 v 1 v_1 v1 -> v 1 v_1 v10 v 1 v_1 v1 -> v 0 v_0 v0 -> v 1 v_1 v110 + 6 = 16× v 1 v_1 v1 -> v 2 v_2 v24 v 1 v_1 v1 -> v 0 v_0 v0 -> v 2 v_2 v210 + 13 = 23× v 2 v_2 v2 -> v 1 v_1 v1 ∞ \infty ∞ v 2 v_2 v2 -> v 0 v_0 v0 -> v 1 v_1 v15 + 6 =11√ v 2 v_2 v2 -> v 2 v_2 v20 v 2 v_2 v2 -> v 0 v_0 v0 -> v 2 v_2 v25 + 13 = 18× 所以,在 v 2 v_2 v2 -> v 1 v_1 v1之间加入点 v 0 v_0 v0作为中转。这里没有考虑在 v 0 v_0 v0 -> v 0 v_0 v0、 v 0 v_0 v0 -> v 1 v_1 v1、 v 0 v_0 v0 -> v 2 v_2 v2、 v 1 v_1 v1 -> v 0 v_0 v0、 v 2 v_2 v2 -> v 0 v_0 v0中加入 v 0 v_0 v0作为中转,因为这没有意义;我们将计算得出的结果反映在下图中,将 A ( 1 ) A^{(1)} A(1)[ v 2 v_2 v2][ v 1 v_1 v1]的值置为11,表示在加入 v 0 v_0 v0作为中转之后,最短路径的长度由 ∞ \infty ∞变为了11, A ( 1 ) A^{(1)} A(1)[ v 2 v_2 v2][ v 1 v_1 v1]的值置为0,表示 v 2 v_2 v2 到 v 1 v_1 v1这个路径路径中,加入了 v 0 v_0 v0作为中转点。
今天这篇是接上上篇RPC原理之后这篇是讲如何使用go本身自带的标准库RPC。这篇篇幅会比较短。重点在于上一章对的补充。
文章目录 RPC包的概念使用RPC包服务器代码分析如何实现的?总结Server还提供了两个注册服务的方法 客户端代码分析如何实现的?如何异步编程同步?总结 codec/序列化框架使用JSON协议的RPC RPC包的概念 回顾RPC原理
看完回顾后其实就可以继续需了解并使用go中所提供的包。
Go语言的 rpc 包提供对通过网络或其他i/o连接导出的对象方法的访问,服务器注册一个对象,并把它作为服务对外可见(服务名称就是类型名称)。
注册后,对象的导出方法将支持远程访问。服务器可以注册不同类型的多个对象(服务) ,但是不支持注册同一类型的多个对象。
Go官方提供了一个RPC库: net/rpc。
包rpc提供了通过网络访问一个对象的输出方法的能力。
服务器需要注册对象,通过对象的类型名暴露这个服务。
注册后这个对象的输出方法就可以远程调用,这个库封装了底层传输的细节,包括序列化(默认GOB序列化器)。
对象的方法要能远程访问,它们必须满足一定的条件,否则这个对象的方法会被忽略:
方法的类型是可输出的方法本身是可输出的方法必须由两个参数,必须是输出类型或者是内建类型方法的第二个参数必须是指针类型 方法返回类型为error 所以一个输出方法的格式如下:
func (t *T) MethodName(argType T1, replyType *T2) error 这里的T、T1、T2能够被encoding/gob序列化,即使使用其它的序列化框架,将来这个需求可能回被弱化。
第一个参数(T1)代表调用者(client)提供的参数第二个参数(*T2)代表要返回给调用者的计算结果方法的返回值如果不为空, 那么它作为一个字符串返回给调用者(所以需要一个序列化框架)如果返回error,则reply参数不会返回给调用者 使用RPC包 简单例子,是一个非常简单的服务。
我们在这个里面就搞1和12就好:
在这个例子中定义了一个简单的RPC服务器和客户端,使用的方法是一个
第一步需要定义传入参数和返回参数的数据结构
type Args struct { A, B int } type Quotient struct { Quo, Rem int } 第二步定义一个服务对象,这个服务对象可以很简单。
比如类型是int或者是interface{},重要的是它输出的方法。
type Arith int 第三步实现这个类型的两个方法, 乘法和除法:
func (t *Arith) Multiply(args *Args, reply *int) error { *reply = args.
系列文章目录 前言 技术委员会 (Technical Committees,TC) 专注于 IEEE 机器人与自动化学会的研究内容,跟踪技术发展并鼓励在以下方面进行创新:应用(applications)、理论(theory)、模型(models)、度量(metrics)、实验(experiments)、架构(architectures)、产品(products)、计划(initiatives)和其他技术领域。
45 个技术委员会鼓励在特定领域开展研究。当某一主题领域发展壮大、相关性日益增强或超出现有技术委员会的范围时,就会增加新的技术委员会。
技术委员会是会员资格的一个重要优势,可促进领域内的进一步合作与交流。
一、Technical Committees 成功的技术合作社区如果已经建立了良好的社区,并举办了相关的 RAS 会议或期刊,则可以申请成为技术社区。这将为他们提供一个进一步发展、提高知名度和获得 RAS 支持的机制。
Haptics
Soft Robotics
二、蓝丝带技术委员会 成长中和活跃的技术合作机构可申请成为蓝丝带技术合作机构。这将为它们提供一个进一步发展、提高知名度和获得 RAS 支持的机制。
Agricultural Robotics and Automation
Model-Based Optimization for Robotics
Multi-Robot Systems
三、全部技术委员会 Aerial Robotics and Unmanned Aerial Vehicles
Agricultural Robotics and Automation
Algorithms for Planning and Control of Robot Motion
Automation in Health Care Management
Automation in Logistics
Autonomous Ground Vehicles and Intelligent Transportation Systems
一、tqdm简介 tqdm是一个python进度条库,可以在 Python长循环中添加一个进度提示信息。
二、3种使用方法 1.tqdm(range)-自动更新 import time from tqdm import range # 自动更新 for i in tqdm(range(10)): # 共可以更新10次进度条 time. Sleep(0.5) # 每次更新间隔0.5s range(10)意味着这里的进度条可以更新10次,由于这里是自动更新,所以一次循环就会更新进度条1,每次更新间隔0.5s。
2.trange()-自动更新 import time from tqdm import trange for i in trange(10): time.sleep(0.5) 这个的效果和方法1一样。
3.手动控制更新 from tqdm import tqdm # 用with语句,进度条完成后会自动关闭 with tqdm(total=10) as pbar: for i in range(10): time. Sleep(0.5) pbar.update(1) # 变量在外部创建,进度结束后手动关闭 phar = tqdm(total=100) for i in range(100): time.sleep(0.1) phar.update(1) phar.close() 这里的total=10意味着这里的进度条可以更新十次,由于这里是手动更新,需要使用update()方法,update(1)意味着每次更新进度1,每次更新间隔0.5s。
三、应用举例 以方法3在有关代码中的使用为例,其代码可以这样写:
1 引言 本博文介绍NR NG-RAN的网络节点间的接口以及无线协议框架。网络接口介绍包括RAN和NGC之间的NG接口;无线协议框架包括用户面和控制面协议。
2 NG接口 2.1 NG用户面接口 NG-U (user plane interface)是NG-RAN节点与UPF之间的接口。NG接口的用户平面协议栈如图1所示。传输网络层建立在IP传输之上,在UDP/IP之上使用GTP-U承载NG-RAN节点与UPF之间的用户平面PDU。
图1 NG-U协议栈 NG-U在NG-RAN节点和UPF之间提供用户平面PDU下发。
2.2 NG控制面接口 NG控制平面接口NG-C(control plane interface)是NG- RAN节点与AMF之间的接口。NG接口的控制平面协议栈如图2所示。传输网络层建立在IP传输的基础上。为了可靠地传输信令消息,在IP之上添加了SCTP。应用层信令协议称为NGAP (NG应用协议)。SCTP层为应用层消息的传递提供了保证。在传输中,采用IP层点到点传输的方式来传递信令PDU。
图2 NG-C协议栈 NG-C提供以下功能:
ng接口管理;ue上下文管理;ue移动性管理;传送NAS讯息;分页;pdu会话管理;配置转移;警告消息传输。 3 Xn接口 3.1 Xn用户面接口 Xn用户平面(Xn-U)接口在两个NG-RAN节点之间定义。Xn接口的用户平面协议栈如图3所示。传输网络层建立在IP传输之上,在UDP/IP之上使用GTP-U承载用户平面PDU。
图3 Xn-U协议栈 Xn-U提供用户平面PDU的非可靠下发,支持以下功能:
数据转发;流量控制。 3.2 Xn控制面接口 在两个NG-RAN节点之间定义Xn控制平面接口(Xn-C)。Xn接口的控制平面协议栈如图4所示。传输网络层建立在IP之上的SCTP之上。应用层信令协议称为XnAP (Xn应用协议)。SCTP层提供应用层消息的可靠的传递。在传输IP层,使用点对点传输来传送信令PDU。
图4 Xn-C 协议栈 Xn-C接口支持以下功能:
xn接口管理;ue移动性管理,包括上下文传输和RAN分页;双连接(DC)。 4 无线协议栈框架 4.1 用户面协议栈 如下图所示为用户平面的协议栈,其中SDAP、PDCP、RLC和MAC子层(在网络侧以gNB终止)执行L2相关的功能。
图5 用户面协议栈 4.2 控制面协议栈 控制平面协议栈如下图所示,其中:
PDCP、RLC和MAC子层(在网络端以gNB终止)执行L2的功能;RRC(在网络端以gNB终止)执行RRC的功能;nas控制协议(在网络端以AMF终止)执行TS 23.501中列出的功能,例如:身份验证、移动性管理、安全控制……
图6 控制面协议栈 5 参考文献 3GPP TS 38.300
目录
安装docker
docker安装MySQL5.7.37
安装MySQL
方式一:docker中MySQL时区调整
方式二:docker中MySQL时区调整
docker安装MySQL8.0.27
docker安装redis5.0.14
云服务器上安装jdk1.8
安装docker 1、先卸载docker,因为有一些服务器上存在已经安装好的docker
sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine 如果之前没有安装过,出现的内容如下:
2、执行安装yum-utils指令
sudo yum install -y yum-utils 3、配置docker的地址,就是指定repo所在地
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 4、安装docker,中途遇到的让你输入y/n的,都输入 y 就行。
sudo yum install docker-ce docker-ce-cli containerd.io 5、启动docker
sudo systemctl start docker 6、查看docker版本号
docker -v 查看目前有哪些镜像: docker images
说明目前是空的。
7、设置docker开机自动启动
systemctl enable docker 8、重启docker
sudo systemctl restart docker 9、配置阿里镜像加速
在Redis6之前的版本中,因安全认证的主要方式是使用Redis实例的密码进行基础控制,而无法按照不同的应用来源配置不同账号以及更细粒度的操作权限控制来管理。本文先从client list中的信息入手,逐步了解Redis的客户端名设置、用户设置及权限控制管理。
1. 客户端名
1.1 查看客户端连接情况
在Redis4版本中,使用 client list 命令查看客户端连接情况的时候可以发现,有的name中有名字,而大部分是没有内容的。有的人误以为这个名称是Redis的登录用户名。例如:
127.0.0.1:6379> client list id=7 addr=127.0.0.1:50194 fd=7 name=testuser age=1222 idle=1185 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client id=8 addr=127.0.0.1:50238 fd=8 name= age=1180 idle=1174 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client id=9 addr=127.0.0.1:51394 fd=9 name= age=3 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client 而client list命令的结果中的每一列的含义如下:
打开anaconda prompt 进入zmcpytorch虚拟环境中 使用命令conda activate zmcpytorch,激活虚拟环境
conda list 查看所存在的包,没有pandas
输入pip install pandas 下载完成
在计算和数据中心、军事和航天、政府、仪器与测量、金融服务和广播和视频等行业,需要高可靠性的硬件和软件产品,帮助客户更快地开发部署新一代产品,减少技术和市场风险,我司研发的低延迟TCP/IP的IP核的传输速率高于传统网口,延迟较低,可以解决网络通信、数据包处理、云储存、和加速算法等应用遇到的技术挑战。
低延迟TCP/IP的IP核有以下特点:
●10G以太网连接。
●完整的RTL层1、2、3和4,包括专有的超低延迟全硬件TCP/IP、ARP、ICMP、MAC和PC实现。
●时钟可配置为250兆赫,以改善延迟结果。
●易于使用的标准化Avalon和AXI-4接口。
●每个FPGA有多个实例,每个实例有多个逻辑接口,每个接口都具有唯一的IPv4、MAC地址、VLAN ID、网关和掩码。
●每个实例可使用128个TCP会话,每个会话都可以在服务器或客户机模式下动态配置。
IP特性有:
●RTL层:
■layer 1:IEEE802.3
■layer 2:IEEE802.3, ARP
■layer 3:IPv4 和ICMP
■layer 4:TCP (RFC 793)
●TCP 管理
■128个TCP会话
■每个会话都可以在服务器或客户机模式下动态配置
●可配置的TCP选项
■VLAN优先级,在发射时插入PCP和DEI字段
■MSS
■窗口比例系数
■Timestamp
●可定制的最大传输单元
■9000字节的有效载荷,支持从标准帧到巨型帧
●Mac处于混杂模式
■访问Mac Raw TX/RX接口
●多接口
■每个实例有8个逻辑接口
■链接到任何会话
■每个接口可配置VLAN
●Avalon和Axi4-4接口
■128位宽接口,从156.25到250MHz,用于TCP/IP客户端端口
■64位宽的接口,从156.25到250MHz,用于MAC客户端端口(TCP/IP旁路)
●IP 配置/管理
■32位Avalon-MM/AXI- 4 Lite从机控制接口,用于MAC和TCP配置
■可在MAC或TCP会话级别监控的状态和统计信息
●可定制的TCP重传缓冲区
■可定制缓冲区大小(深度和宽度)
■可定制的内部或外部内存支持(DDRX、QDRX等),取决于性能和FPGA大小要求
●物理接口
■PC和PMA之间的PMA并行数据(Altera Stratix V的PMA直接模式和第10代的PC直接模式)
■PC和Mac之间的MII 64位流媒体接口
实测环境
经常遇到需要发送带附件的邮件的功能,特写一份详细的笔记
1、老样子,首先引入依赖 <!--发送邮件的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> <version>2.5.4</version> </dependency> <!--thymeleaf 邮件模板依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <version>2.5.4</version> </dependency> 2、编写一份邮件的html模板 邮件模板放在 resource/templates路径下
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>template</title> <style> p { font-size: larger; font-weight: bold; } #yes { padding: 10px; font-size: 16px; border: none; border-radius: 5px; background-color: orange; color: white; } #no { padding: 10px; font-size: 16px; border: none; border-radius: 5px; background-color: darkgrey; color: white; } div { width: 100%; margin: 0 auto; } div.
函数题 6-1 二分查找 分数 15
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
本题要求实现二分查找算法。
函数接口定义: Position BinarySearch( List L, ElementType X );
其中List结构定义如下:
typedef int Position; typedef struct LNode *List; struct LNode { ElementType Data[MAXSIZE]; Position Last; /* 保存线性表中最后一个元素的位置 */ };
L是用户传入的一个线性表,其中ElementType元素可以通过>、==、<进行比较,并且题目保证传入的数据是递增有序的。函数BinarySearch要查找X在Data中的位置,即数组下标(注意:元素从下标1开始存储)。找到则返回下标,否则返回一个特殊的失败标记NotFound。
裁判测试程序样例: #include <stdio.h> #include <stdlib.h> #define MAXSIZE 10 #define NotFound 0 typedef int ElementType; typedef int Position; typedef struct LNode *List; struct LNode { ElementType Data[MAXSIZE]; Position Last; /* 保存线性表中最后一个元素的位置 */ }; List ReadInput(); /* 裁判实现,细节不表。元素从下标1开始存储 */ Position BinarySearch( List L, ElementType X ); int main() { List L; ElementType X; Position P; L = ReadInput(); scanf("
最近有哥们推荐了一个现代化Linux开源管理面板1Panel,开源且稳定,懒是第一生产力,虽然命令行很灵活,但图形化界面真的是懒人刚需,本期在树莓派部署一下1Panel,让树莓派Linux运维更省力,进一步降低玩树莓派的门槛。开源地址:https://github.com/1Panel-dev/1Panel
安装1Panel curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh 如果我们直接访问 38414 端口,会提示无权限,一定要访问完整的带路由的路径,如果忘了访问路径,在树莓派终端输入1pctl user-info 即可查看
输入完整url, 输入用户名,密码,登录!
在首页我们可以看到树莓派当前的运行状态,以及系统的信息,CPU 90%的利用率,内存60%的利用率,树莓派被zhaoolee压榨的还是比较到位的,确实没有吃灰!(树莓派:我谢谢你!)
我们还可以通过容器菜单,查看各个Docker容器的运行情况
通过浏览器下载服务器文件到本地 我们可以直接通过浏览器下载树莓派的文件到本地
打开浏览器就可以使用ssh 我们可以通过浏览器直接使用终端命令行,操控树莓派
通过应用商店安装软件 1Panel还有一个非常方便的的功能,就是一键安装各种环境以及开源项目,这里我们演示安装一个网易云第三方客户端YouPlayMusic
点击安装后,会有一个面板确认信息,为了方便演示,我们允许外部访问
按照上图给出的提示,我们可以通过访问40075端口, 查看树莓派运行的yesplaymusic
将1Panel映射到公网 如果你想在任何有互联网的地方都可以通过1Panel访问自己的树莓派,可以发挥传统艺能,通过frp将1Panel映射到公网,考虑到安全性,我会使用https加密,将 https://1panel.fangyuanxiaozhan.com/ 的访问,转发到家庭树莓派的38414端口
首先在树莓派的 frpc.ini添加以下配置,重启树莓派的frpc服务,使其生效
[1panel-fangyuanxiaozhan-com-38414] type = tcp local_ip = 127.0.0.1 local_port = 38414 remote_port = 38414 然后在云服务器的nginx添加配置文件 /etc/nignx/conf.d/1panel.fangyuanxiaozhan.com.conf
upstream 1panel_fangyuanxiaozhan_com { server 127.0.0.1:38414; } server { server_name 1panel.fangyuanxiaozhan.com; listen 80; location / { proxy_pass http://1panel_fangyuanxiaozhan_com; proxy_set_header Host $host:80; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } 通过acme申请证书 domain="
已知市场部有100台设备,研发部24台,销售部50台。利用子网划分将网段192.168.1.0 /24划分
市场部划分 市场部需要100个ip,借一位则有126个ip可使用掩码位数为25 借一位分别为
192.168.1.0 | 00000000
192.168.1.1 | 00000000
(我们用192.168.1.0 | 00000000)网络号192.168.1.0/25掩码为255.255.255.128
可用ip为 192.168.1.1-192.168.1.126
销售部划分 销售部需要50个ip,借两位则有62个ip可使用掩码位数为26 (剩下192.168.1.1 | 00000000)
借两位分别为
192.168.1.10 | 000000
192.168.1.11 | 000000
(我们用192.168.1.10 | 000000)网络号192.168.1.128 /26掩码为255.255.255.192
可用ip为 192.168.1.129-192.168.1.190
研发部划分 研发部需要24个ip,借三位则有30个ip可使用掩码位数为27
(剩下192.168.1.11 | 000000)
借三位分别为
192.168.1.110 | 00000
192.168.1.111 | 00000
(我们使用192.168.1.110 | 00000)网络号192.168.1.192 /27掩码为255.255.255.224
可用ip为 192.168.1.193-192.168.1.222
剩下192.168.1.111 | 00000
路由接口地址划分 路由接口ip,划分两个就可以那么借6位可用IP数就是2
192.168.1.111000 | 00
网络号192.168.1.224/30掩码为255.255.255.252可用IP为192.168.1.225-192.168.1.226
192.168.1.111001 | 00
网络号192.168.1.228/30掩码为255.255.255.252可用IP为192.168.1.229-192.168.1.230
(先将需求多的划分出去会方便很多)
问题 ps: 请先阅读到最后,因为中间包含反思和尝试,并非解决方案。
首先是因为遇到一个问题:矢量边界有偏移导致裁剪的结果出现很多细碎多边形,这样的结果是不能使用的。
具体为:
我获得了四川的一部分数据,该数据中包含了成都市街道尺度,我刚开始先是简单地将成都矢量与该四川数据进行裁剪,得到如下结果
可见是因为我的两个数据边界不是完全符合的。
解决问题 那么有这样一个想法,就是,如果我能根据 成都市的边界数据 来获取到与成都边界有交集的地方,那么我就得到了成都市的街道数据,即原数据还是那个四川的数据,只是保留了成都市的街道那部分。
思路为:先用identify把四川数据标识上有成都数据属性,再按属性选择,从四川数据中选取有成都数据属性的那部分,下面来试试看:
chengdu_county是标识后的结果,也就是说chengdu_county中有了chengdu的属性abcode(其实这里的属性不一定选择abcode,可以选择任一chengdu属性中的属性,想想看是不是这样?)
那么我把abcode属性有值的选择出来,导出为新的数据,就解决问题了
结果too young too simple 😦
接下来我再尝试另一个工具,SpatialJoin空间连接,目的是为了让这个四川数据带上成都的abcode属性
空间连接后,按属性选择,选择abcode有值的记录
导出要素
还好多出来的面不多,这次我就手动编辑了
ok,没有细碎多边形。解决了
更简单的解决方式 忘记了按位置选择这个工具
可以直接得到与chengdu有交集的四川数据
导出数据再删多余面数据,就解决问题了。
一样,直接得到了空间连接再按属性选择后的结果,省了两步。
总结 矢量叠加操作分为:相交(Intersect)、标识(又称交补集,Identify)、裁剪(Clip)、联合(Union)、追加(Append)、合并(Merge)以及融合(Dissolve)等。
合并(Merge) 相交(Intersect) 标识(Identify) 裁剪(Clip) 联合(Union) 融合(Dissolve) 追加(Append)
新装的Ubuntu 18.04版本默认没有安装net-tools,导致ifconfig命令用不了。于是想安装net-tools,但是没有网,一直安装不上。找了好多资料,终于找到一个有效的离线安装办法。
ubuntu中未安装net-tools,需要离线安装:
net-tools官方下载
下载对应版本文件
例如amd64版本:
http://mirrors.kernel.org/ubuntu/pool/main/n/net-tools/net-tools_1.60+git20161116.90da8a0-1ubuntu1_amd64.deb
下载完毕后,执行deb包安装。
1.sudo dpkg -i xxx.deb
文章目录 1.1 服务架构演变1.1.1 单体架构1.1.2 分布式架构1.1.3 微服务 1.1 服务架构演变 1.1.1 单体架构 单体架构:将业务的所有功能在一个项目里开发,打包部署。
优点:
架构简单
部署成本低(将项目打包,部署到一台 Tomcat 上,将来为了应对并发,多搞几台机器,形成负载均衡的集群就行了)
耦合度高(升级、拓展困难、大型项目一定会作分布式架构)
1.1.2 分布式架构 分布式架构:根据业务的功能模块对系统作拆分,每个模块独立开发,称为一个服务。
优点:耦合度低(服务升级和拓展方便、单独模块进行技术升级对其他模块也没有影响) 服务治理
分布式架构虽然降低了服务耦合,但是也有几个问题需要考虑:
服务拆分粒度。(怎么拆?哪几个服务作为独立模块呢?哪几个业务在一起呢?)服务集群地址如何维护?(比如一个模块有上百台机器,将来我要调用你,我怎么知道你上百台机器的地址?肯定不可能写死,万一上线的时候,一部署地址变了,我再改?肯定不行,这个地址是要方便维护的)服务之间如何实现远程调用?(单体项目:订单需要用到商品信息,直接调用 Service 就行了,因为部署在一个项目里,大家可以互相调。作了拆分,变成了2个服务,部署在独立的机器上,那就不能随便调用了,只能通过一个服务向另一个服务发请求,这个过程叫远程调用)服务健康状态如何感知?(我要调用你的服务,我怎么知道你的服务的健康状态?万一你挂了,我调用你,我也阻塞了,这叫级联失败)
1.1.3 微服务 微服务是一种经过良好架构设计的分布式架构方案。
在 Vue3 +Vite环境中使用.env 环境配置文件 1、安装 dotenv2、项目根目录创建 .env相关环境配置文件3、在页面或者组件使用当前运行环境配置 1、安装 dotenv npm install dotenv --save 2、项目根目录创建 .env相关环境配置文件 .env.development 开发环境配置文件
.env.production 生产环境配置文件
示例创建一个 .env.development 开发环境配置文件内容
这里要注意,环境配置变量名必须是要 VITE_ 开头的才会被扫描然后暴露出去,在 Vue2里面则是 VUE_开头
# 开发环境配置 ENV = 'development' # api请求地址 VITE_APP_BASE_API = 'http://127.0.0.1:12581/luk' 3、在页面或者组件使用当前运行环境配置 在组件或者页面使用 import.meta.env 调用相关的配置环境变量
页面Demo
<template> </template> <script setup lang="ts"> import { onActivated } from "vue"; const baseApiUrl = import.meta.env.VITE_APP_BASE_API onMounted(() => { }) onActivated(() => { console.info('当前运行环境:', import.meta.env) console.info('API请求地址', baseApiUrl) }) </script>
目录
将数据存储到文件中
创建文件和保存数据
读取文件
SharedPreferences存储
存储数据到SharedPreferences中
Context类中的getSharedPreferences()方法
Activity类中的getPreferences()方法
从SharedPreferences中读取数据
SQLite数据库存储
创建数据库
调用数据库
操作数据库
增
删
改
查
升级数据库
将数据存储到文件中 创建文件和保存数据 Context类中提供了一个openFileOutput()方法,可以用于将数据存储到指定的文件中。这个方法接收两个参数:第一个参数是文件名,在文件创建的时候使用,注意这里指定的文件名不可以包含路径,因为所有的文件都默认存储到/data/data/<package name>/files/目录下;第二个参数是文件的操作模式,主要有MODE_PRIVATE和MODE_APPEND两种模式可选,默认是MODE_PRIVATE,表示当指定相同文件名的时候,所写入的内容将会覆盖原文件中的内容,而MODE_APPEND则表示如果该文件已存在,就往文件里面追加内容,不存在就创建新文件。其实文件的操作模式本来还有另外两种:MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE。这两种模式表示允许其他应用程序对我们程序中的文件进行读写操作,不过由于这两种模式过于危险,很容易引起应用的安全漏洞,已在Android 4.2版本中被废弃。
openFileOutput()方法返回的是一个FileOutputStream对象,得到这个对象之后就可以使用Java流的方式将数据写入文件中了。以下是一段简单的代码示例,展示了如何将一段文本内容保存到文件中:
fun saveFile(saveString: String) { val output = openFileOutput("fileName", Context.MODE_PRIVATE) val writer = BufferedWriter(OutputStreamWriter(output)) writer.use { it.write(saveString) } } 这里通过openFileOutput()方法能够得到一个FileOutputStream对象,然后借助它构建出一个OutputStreamWriter对象,接着再使用OutputStreamWriter构建出一个BufferedWriter对象,这样你就可以通过BufferedWriter将文本内容写入文件中了。
注意,这里还使用了一个use函数,这是Kotlin提供的一个内置扩展函数。它会保证在Lambda表达式中的代码全部执行完之后自动将外层的流关闭,这样就不需要我们再编写一个finally语句,手动去关闭流了,是一个非常好用的扩展函数。
另外,Kotlin是没有异常检查机制(checked exception)的。这意味着使用Kotlin编写的所有代码都不会强制要求你进行异常捕获或异常抛出。即使你不写try catch代码块,在Kotlin中依然可以编译通过。
读取文件 类似于将数据存储到文件中,Context类中还提供了一个openFileInput()方法,用于从文件中读取数据。这个方法要比openFileOutput()简单一些,它只接收一个参数,即要读取的文件名,然后系统会自动到/data/data/<package name>/files/目录下加载这个文件,并返回一个FileInputStream对象,得到这个对象之后,再通过流的方式就可以将数据读取出来了。
以下是一段简单的代码示例,展示了如何从文件中读取文本数据:
fun loadFile(): String { val stringBuilder = StringBuilder() val input = openFileInput("fileName") val reader = BufferedReader(InputStreamReader(input)) reader.use { reader.
TransFusion简介、环境配置与安装以及遇到的各种报错处理 TranFusion简介TransFusion环境配置与安装报错报错一报错二报错三报错四报错五报错六报错七报错八 TranFusion简介 针对以下两个问题:
通过串联或相加融合Lidar和Camera,在图像质量变差时感知性能会下降;稀疏的点云和稠密的图像之间寻找“硬关联”会使图像的语义信息有所损失,而且传感器之间固有的时空特性而难以高质量地校准。 Transfusion提出了一种lidar和camera“软关联”的融合方法,利用点云特征和图像特征初始化object query(可以加速模型训练和收敛),object query首先与lidar特征交互,再与2D图像特征进行交互更新object query,最后通过FFN得到检测结果。Transfusion的网络结构如下图所示:
TransFusion环境配置与安装 基本环境如下:
Linux(Ubuntu 20.04)NVIDIA GeForce RTX 3090NVIDIA显卡驱动版本:12.0CUDA version:11.1 TransFusion环境配置与安装:
#创建conda环境 conda create -n transfusion python=3.7 -y conda activate transfusion # 安装pytorch pip install torch==1.9.1+cu111 torchvision==0.10.1+cu111 torchaudio==0.9.1 -f https://download.pytorch.org/whl/torch_stable.html # 安装mmcv pip install mmcv-full==1.3.11 -f https://download.openmmlab.com/mmcv/dist/cu111/torch1.9.0/index.html # 安装mmdetection pip install mmdet==2.11.0 # 下载TransFusion的Github库 git clone https://github.com/XuyangBai/TransFusion.git cd TransFusion # 编译、安装mmdetection3d pip install -v -e . 报错 报错一 error: subprocess-exited-with-error
× Running setup.
大电流H桥电机驱动电路的设计与解析(包括自举电路的讲解,以IR2104+LR7843为例) 电机驱动板主要采用两种驱动芯片,一种是全桥驱动(如:HIP4082),一种是半桥驱动(如:IR2104)Chapter1 大电流H桥电机驱动电路的设计与解析(包括自举电路的讲解,以IR2104+LR7843为例)一.简介二.示例原理图和PCB展示1.原理图2.PCB 3D图 三.辅助电路部分讲解1.BOOST升压电路2.降压稳压电路3.隔离电路部分 四.搭建的H桥驱动电路详解1.简介2.NMOS管IRLR78433.半桥驱动芯片IR2104S补充总结:4.控制逻辑 Chapter2 【电机驱动芯片(H桥、直流电机驱动方式)——DRV8833、TB6612、A4950、L298N的详解与比较】Chapter3 IR2104电机驱动一、IR2104的引脚定义:二、IR2104的内部原理:三、半桥驱动原理分析四、全桥驱动原理分析五、电感电流回流路径的建立六、自举电容容值的计算与自举二极管选型:七:mos管发热可能的问题八: 推荐阅读 Chapter4 HIP4082电机驱动电路详解一、原理图二、化简电路再做分析的前提三、分析一下自己的理解< 1 > 引脚说明< 2 > MOS管的高端驱动和低端驱动< 3 > 电机驱动电路分析< 4 > 具体到通过PWM控制电机占空比 电机驱动板主要采用两种驱动芯片,一种是全桥驱动(如:HIP4082),一种是半桥驱动(如:IR2104) Chapter1 大电流H桥电机驱动电路的设计与解析(包括自举电路的讲解,以IR2104+LR7843为例) 原文链接:https://blog.csdn.net/qq_44897194/article/details/107397079
一.简介 之前介绍过H桥电机驱动电路的基本原理,但是以集成的电机驱动芯片为示例。这些集成的芯片使用起来比较简单,但是只能适用于一些小电流电机,对于大电流的电机(比如:RS380和RS540电机),则不能使用这些集成的芯片(否则会导致芯片严重发热并烧毁)。
此时便需要自行用半桥/全桥驱动芯片和MOS管搭建合适的H桥电机驱动电路实现对大电流电机的驱动控制。
二.示例原理图和PCB展示 此原理图和PCB采用的是网上分享的电路设计(IR2104半桥驱动+LR7843MOS管),为了便于焊接,对其中的一些封装进行了修改,并重新布线。
该电机驱动板有两个H桥电路,可以同时控制双路电机。可通过相应的控制信号来控制电机的转速和正反转。
原网址:电赛必备,IR2104S半桥驱动MOS管电机驱动板(可下载工程)
1.原理图 2.PCB 3D图 三.辅助电路部分讲解 本驱动模块默认采用7.4V的锂电池组接入右侧的P1端子进行供电。
1.BOOST升压电路 ★BOOST升压电路采用的是MC34063这款芯片。此模块主要是将7.4V的输入电压升到12V后为后面的IR2104S半桥驱动芯片供电(需要12V的原因将在下面介绍)。此芯片的工作原理在此不多做介绍,可自行下载数据手册进行学习(后期会对此专门写一篇博客介绍)。
注意事项:
(1).此BOOST电路模块是此驱动板中较为容易出问题的部分,因此焊接时需要先对其进行焊接调试,确认没有问题后再进行后续的焊接。
(2).此电路需要尤其注意0.22Ω的精密电流检测电阻,如果电阻质量不合格很容易出现问题,导致电路不能正常工作。
如有其他问题可参看此篇文章:MC34063升压电路中常见的几种问题
2.降压稳压电路 ★降压稳压电路采用的是MIC5219这款LDO芯片。此电路模块将7.4V的输入电压降压稳压到3.3V给后面的74LVC245芯片供电。类似芯片较多,使用也较为简单。
如需要详细了解其工作原理,可参看此篇文章:LDO低压差线性稳压芯片的使用(LM1117)
3.隔离电路部分 在设计电机驱动板时,很多都会有一个用于隔离的电路模块。主要用于将控制器与H桥驱动电路隔离开,防止损坏控制器。
此电机驱动板采用了74lvc245这款三态输出的收发器芯片作为隔离芯片。也可以使用74HC125(三态四线非反相缓冲器)或74HC244(三态八线非反相缓冲器)。具体使用说明可参考相应的数据手册。
四.搭建的H桥驱动电路详解 1.简介 在学习此部分之前,需要先掌握基础H桥驱动的工作原理,具体可参看此篇博客:电机驱动芯片(H桥、直流电机驱动方式)
自行搭建的H桥驱动电路一般都包括两个部分:半桥/全桥驱动芯片和MOS管。自行搭建的H桥驱动所能通过的电流几乎由MOS管的导通漏极电流所决定。因此,选择适当的MOS管,即可设计出驱动大电流电机的H桥驱动电路。
2.NMOS管IRLR7843 在选择MOS管搭建H桥时,主要需注意以下一些参数:
★1.漏极电流(Id):该电流即限制了所能接入电机的最大电流(一般要选择大于电机堵转时的电流,否则可能在电机堵转时烧毁MOS管),LR7843的最大漏极电流为160A左右,完全可以满足绝大部分电机的需要。
★2.栅源阈值电压/开启电压(Vth):该电压即MOS管打开所需的最小电压,也将决定后续半桥驱动芯片的选择和设计(即芯片栅极控制脚的输出电压)。LR7843的最大栅源阈值电压为2.3V。
★3.漏源导通电阻(Rds):该电阻是MOS管导通时,漏极和源极之间的损耗内阻,将会决定电机转动时,MOS管上的发热量,因此一般越小越好。LR7843的漏源导通电阻为3.3mΩ。
★4.最大漏源电压(Vds):该电压是MOS管漏源之间所能承受的最大电压,必须大于加在H桥上的电机驱动电压。LR7843的最大漏源电压为30V。满足7.4V的设计需要。
3.半桥驱动芯片IR2104S 在H桥驱动电路中,一共需要4个MOS管。而这四个MOS管的导通与截止则需要专门的芯片来进行控制,即要介绍的半桥/全桥驱动芯片。
★所谓半桥驱动芯片,便是一块驱动芯片只能用于控制H桥一侧的2个MOS管(1个高端MOS和1个低端MOS,在前述推荐的博客中有介绍)。因此采用半桥驱动芯片时,需要两块该芯片才能控制一个完整的H桥。
★相应的,全桥驱动芯片便是可以直接控制4个MOS管的导通与截止,一块该芯片便能完成一个完整H桥的控制。
这里使用的IR2104便是一款半桥驱动芯片,因此在原理图中可以看到每个H桥需要使用两块此芯片。
1.典型电路设计(来源于数据手册)
2.引脚功能(来源于数据手册)
当你想给你的Python程序增添一些趣味和个性时,Emoji模块是一个很有用的工具。Emoji模块允许你在Python中使用各种表情符号,从笑脸到动物,甚至是食物和天气等。在本篇博客中,我们将介绍如何在Python中使用Emoji模块,并展示一些实际的例子。
首先,确保你已经在Python环境中安装了Emoji模块。你可以使用以下命令来安装它:
pip install emoji 一旦安装完成,你就可以开始在你的Python程序中使用Emoji模块了。下面是一些常见的用法示例:
C:\pythoncode\new\emojiexample.py
打印表情符号 你可以使用Emoji模块的emojize函数来打印表情符号。该函数接受一个字符串作为参数,其中包含了所需的表情符号的别名或Unicode代码点。下面是一个简单的例子:
import emoji # 打印笑脸表情符号 print(emoji.emojize(":smile:")) # 打印心形表情符号 print(emoji.emojize(":heart:")) # 打印猫的表情符号 print(emoji.emojize(":cat:")) # 打印自定义表情符号 print(emoji.emojize(":thumbs_up:")) # 打印一些组合表情符号 print(emoji.emojize(":thumbs_up: :smile: :thumbs_up:")) # 使用Unicode代码点直接打印表情符号 print(emoji.emojize("\U0001F600")) # 使用别名打印表情符号 print(emoji.emojize(":grinning_face_with_big_eyes:")) 运行上述代码,你将看到输出的结果包含了笑脸、心形和猫的表情符号。
自定义表情符号 除了预定义的别名和Unicode代码点,Emoji模块还允许你创建自定义的表情符号。你可以使用emojize函数并传递自定义别名或Unicode代码点来打印所需的表情符号。例如:
import emoji # 打印自定义的表情符号 print(emoji.emojize(":thumbs_up:")) 组合表情符号 Emoji模块还允许你组合多个表情符号以创建更复杂的表情。你可以使用空格或其他字符将多个表情符号连接在一起。例如:
import emoji # 打印一些组合表情符号 print(emoji.emojize(":thumbs_up: :smile: :thumbs_up:")) 其他用法 Emoji模块还提供了其他一些有用的函数和方法,例如:
emoji.demojize():将表情符号转换为对应的别名。emoji.emoji_count():计算字符串中包含的表情符号数量。emoji.is_emoji():检查一个字符是否为表情符号。emoji.get_emoji_regexp():获取用于匹配表情符号的正则表达式。 你可以查阅Emoji模块的官方文档以了解更多的用法和函数。
参考:
Emoji模块中包含了大量的表情符号,这里列举一些常见的表情符号作为示例:
😄 表示笑脸❤️ 表示心形🐱 表示猫的表情:thumbs_up: 表示竖起大拇指:thumbs_down: 表示竖起小拇指🙏 表示合十的手势🔥 表示火焰⭐️ 表示星星☀️ 表示阳光🌔 表示月亮🌈 表示彩虹☁️ 表示云朵☔️ 表示雨伞☕️ 表示咖啡🍕 表示比萨饼🎁 表示礼物🚀 表示火箭⌛️ 表示沙漏⏰ 表示闹钟 这只是一小部分Emoji模块中可用的表情符号示例。Emoji模块支持大量的表情符号,你可以在官方的Emoji Cheat Sheet(https://www.
NuGet包: 1.SqlSugarCore
2.System.Data.SqlClient
Program配置: builder.Services.AddScoped<ISqlSugarClient>(x => { SqlSugarClient db = new SqlSugarClient(new ConnectionConfig() { ConnectionString = "Data Source=.;Initial Catalog=hx;Integrated Security=True;TrustServerCertificate=True", // 替换为实际的数据库连接字符串 DbType = DbType.SqlServer, // 数据库类型,这里以 SQL Server 为例 IsAutoCloseConnection = true, // 自动关闭连接 MoreSettings = new ConnMoreSettings() { IsWithNoLockQuery = true, // 默认查询时加上 WITH (NOLOCK) IsAutoRemoveDataCache = true// 自动清除缓存 } }); // 配置输出 SQL 语句到控制台 db.Aop.OnLogExecuting = (sql, pars) => { Console.WriteLine($"Executing SQL: {sql}\nParameters: {JsonSerializer.Serialize(pars)}\n"); }; return db; }); 生成实体类: 可以放在一个控制台程序中,需要的时候在运行就好
今天来为大家分享一波关于缓冲区的知识!那么既然我们要谈缓冲区,那么就得从是什么?为什么?有什么作用这几个方面来谈论一下缓冲区!然后再通过一些代码来更加深刻的理解缓冲区的知识!
引言: 是什么? 从最简单的理解方面来,我们可以将缓冲区理解成一块内存!那么这块内存是从哪里来的呢?在linux中一般我们所说的缓冲区都是由C提供的语言级别的缓冲区!
干什么的? 那么缓冲区的作用主要是用来干什么的呢?可以从我们生活中的例子来理解!假设你的朋友小张下个月就要过生日了,你要送他一个生日礼物!但是你们两个距离很远!一个在西藏,一个在海南!如果让你自行将生日礼物送给他,那么无疑将会浪费你的很多成本!但是现实中存在快递站,只需要你下楼将礼物交付给快递站,然后由快递站代替你送过去即可!那么在本例子内,快递站的作用就是一个缓冲区的作用!
为什么要存在缓冲区? 根据上面提到的例子,很容易理解,因为有了快递站的存在,使我们方便了很多!所以类似于此,缓冲区存在的意义就是为了提高效率,减少我们的成本!
下面通过一段代码来证明一下缓冲区确实存在!
我们用户通常写程序在屏幕上打印一段文字的时候!其中就利用到了缓冲区!例如下面这个例子!
运行这段程序之后,显示屏上并没没有立刻打印出“hello linux”,这是为什么呢?根据我们所了解到的知识,程序是自上向下运行的,运行到sleep的时候,printf语句一定是执行过了,但是为什么没有打印出结果呢?根据此例子可以充分的证明缓冲区的存在!!既然证明了缓冲区的存在,那么我们将来一步一步的进行分析缓冲区的相关知识1
那么从系统角度来将该如何理解的呢?
从操作系统角度上来看!用户输入一段指令,该指令并没有直接传递到内核文件内存中!而是将用户输入的指令存放到了C提供的语言级别的缓冲区内!然后在C语言的缓冲区中经过刷新之后!再传递到内核结构中的文件缓冲区中!最后系统会定期的将内存的数据刷新到磁盘中!此阶段也可以称之为刷新!在此,我们提到了两个缓冲区,一个是用户层的C语言提供的语言级别的缓冲区,一个是内核结构中的内核文件缓冲区!一般我们所考虑的都是C语言提供的语言级别的缓冲区!
缓冲区的一些特性: 根据缓冲区能够存储一定的数据可以推出:缓冲区一定存在着刷新的方式!
1.无缓冲(立即刷新!)
2.行缓冲(行刷新!)
一般对于显示器文件,都是基于行缓冲的模式!
3.全缓冲(存放满然后进行刷新!)
对于磁盘文件,都是基于全缓冲的方式!
那么根据以上的特征,缓冲区也会有着特殊的情况!
1.强制刷新!
2.进程退出后,会自动进行刷新!(无论是否满足刷新的条件!)
实例:充分理解缓冲区 下面通过一段代码来充分理解缓冲区中的行缓冲和全缓冲!
上面代码运行过后,每行代码都打印了出来!这是为什么呢?刚才不是还说是存在缓冲区的么?其实不难理解,因为每段代码都有了\n换行符,强制让缓冲区内的数据进行刷新!所以数据都原样的打印了出来!!
那么将上面的代码经过简单的修改就会出现另外一种结果!
经过上面代码简单的修改,我们发现C函数的调用都打印了两次,而是用系统调用的write确只调用了一次!这是为什么呢?其实很简单!
我们可以看出,我们将输出结果由原来的行缓冲转化成了全缓冲(因为将结果打印到了log.txt文本文件中,文本文档默认为全缓冲的刷新方式!)所以只有当将缓冲区填满的时候,才会进行刷新!才能打印到显示屏中!又因为调用了fork函数,创建了新的子进程!根据fork的特性会继承父进程的代码和数据块!因为此时代码仍然在缓冲区内!所以子进程也会继承这些相同的代码和数据块!然后当一个进程结束后,就会发生写时拷贝!这是因为当一个进程退出的时候,一般都会对缓冲区的数据进行刷新,那么算不算清空或写入的操作呢?答案是肯定的!当时算!所以就会发生写时拷贝!所以可以推出,一旦一个进程退出,那么就会发生写时拷贝!
根据上图结果看出,系统调用write只打印了一次!从这里可以推出:write没用使用C语言的缓冲区!因为C语言的一些函数,大多都是对系统调用的封装!大多都是因为封装的原因!而导致他们使用C提供的缓冲区!而系统调用处于内核级别,在用户级别的下面,直接将数据写入到内核文件系统中!所以不使用C提供的缓冲区!
实例中的主要知识点: 1.当我们直接向显示器打印的时候,显示器文件的刷新方式是行刷新!而是我们的代码输出的所有字符串,都有\n,fork之前,数据已经全部被刷新!包括systemcall!
2.重定向到log.txt之后,本质是向磁盘文件中写入(而不再是显示器里面!),我们系统对于数据的刷新方式已经由行刷新转化到了全刷新的方式!变成了全缓冲!
3.全缓冲意味着缓冲区变大,实际写入的简单数据,不足以将缓冲区填满!fork执行的时候,数据依然在缓冲区内部!
4.我们目前所谈的缓冲区,是和操作系统没有关系的!只能和C语言本身有关!!
5.C/C++提供的缓冲区,里面保存的一定是用户的数据!其属于当前进程运行的数据!但是如果当把数据交付给OS,这些数据就属于OS了,不再属于该进程了!
6.当进程退出的时候,一般会进行刷新缓冲区,即使我们的数据没有满足刷新条件!
证明缓冲区的存在以及其在内核中的结构! 既然我们都讲了这么多关于缓冲区的知识了,那么我们确实已经知道了缓冲区真实存在!那么能否让我看一看其到底是什么样子的呢?
通过以上函数,我们可以发现,大多的输入输出操作,以及文件的操作都用到了FILE该结构体!那么该结构体之中我们之前知道其包含了文件描述符fd,那么其是否介意再包含一个缓冲区的成员变量呢?答案是当然不介意的啦!
我们可以通过对FILE的观察来看一下缓冲区的真实存在!
我们通过grep指令来查看FILE的路径!然后在FILE内部继续进行查找,最后看到FILE内部有我们熟悉的文件描述符_fileno,以及我们今天所讲的缓冲区的内容!
至此,本文关于缓冲区的介绍到此为止,希望读完本篇文章,能对读者有一定的收获!
Visual Studio Code 1.85 现已发布,具体更新内容如下:
浮动编辑器窗口 - 将编辑器拖放到桌面上。 在此版本中,你可以将编辑器从主窗口移到自己的轻量级窗口中。对一个窗口中的编辑器所做的更改会立即应用到打开编辑器的所有其他窗口。创建浮动编辑器窗口的最简单方法是将编辑器从当前窗口拖出,然后放到桌面的空白处。
新的 workbench.editor.dragToOpenWindow 设置可以禁用这一行为。
此外,还新增了全局和上下文命令,用于将编辑器和编辑器组移动或复制到各自的窗口中:
View: Copy Editor into New Window (workbench.action.editor.copyWithSyntaxHighlightingAction)View: Move Editor into New Window (workbench.action.editor.moveEditorToNextWindow)View: Copy Editor Group into New Window (workbench.action.editor.copyGroupToNextWindow)View: Move Editor Group into New Window (workbench.action.editor.moveGroupToNextWindow)View: New Empty Editor Window (workbench.action.newWindow) 浮动窗口中的编辑器区域可以按照你的要求进行任何复杂的布局。由于终端和搜索结果都可以作为编辑器打开,因此现在也可以在单独的窗口中使用这些功能。
无障碍视图工作流程 - 更顺畅地往返于无障碍视图。更精细的扩展更新控制 - 选择要自动更新的扩展。 Source Control Incoming/Outgoing 视图 - 轻松查看待处理的存储库更改。 JavaScript 堆快照 - 可视化堆快照,包括内存对象图。 TypeScript 从 inlay hints 转到 Definition - 从 inlay hint 悬停跳转到 definition。 Python 类型层次结构显示 - 快速查看和浏览复杂的类型关系。 GitHub Copilot 更新 - 内联聊天改进、Rust 代码解释。 预览:扩展的 Sticky Scroll 支持 - 在树视图和终端中的 Sticky Scroll。
postman设置断言 作为一款接口测试工 具,postman需要对发送请求后返回的结果是否正确做验证,在postman中通过 tests页签做请求的验证,也称为断言。
postman设置断言的流程 1、在tests页签截取要对比的实际响应信息(响应头、响应正文、响应状态码等)
2、利用断言语句 tests[] 或 chai.js 形式把实际响应信息与期望结果对比
3、执行请求进行结果查看
在postman设置断言,存在新老版本的断言语法不一致的情况,目前两种语 法都可以使用: 语法一: tests[‘测试用例名称’] = 逻辑表达式; 断言语法一视图:
postman在tests页签获取响应内容:
tests页签支持javascripts语法,可以把获取的响应内容放入定义的变量中。 然后使用tests[变量名]进行输出。
截取实际响应信息的新老版本代码对比;如下图
1、获取响应行
var code = responseCode.code; //获取响应状态码
var name = responseCode.name; //获取响应状态信息
2、获取响应头
var content_type = postman.getResponseHeader('Content-Type') //获取响应头
var path = postman.getResponseCookie('_ac_app_ua').path ; //获取cookie信息
3、获取响应正文
var body = responseBody
4、获取响应时间
var time = responseTime;
5、利用正则表达式截取部分响应正文
var title = body.match(new RegExp('<title>(.+?)</title>'))[1];
6、响应正文为json时,可以利用postman进行解析再获取部分响应正文
var jsondata = JSON.parse(responseBody); //把响应正文转化为json对象
var token = jsondata.
1 、下载安装包 进入官网下载安装包: MinIO | 高性能、支持原生 Kubernetes的对象存储
信任程序安装,就可以啦
2、启动MinIO 第一步,找到minio.exe所在的目录,在地址栏输入cmd进入cmd窗口。
第二步,输入.\minio.exe server F:\minio 命令启动Minio。F:\minio 为minio上传文件保存目录,可自定义保存目录。 3 、登录MinIO后台 打开MinIO Console地址,输入ACCESS-KEY 和 SECRET-KEY即可登录minio的管理界面了。
4 、修改密码 第一步,找到minio.exe所在目录,进入cmd窗口。
第二步,输入set MINIO_ACCESS_KEY=admin命令,修改ACCESS-KEY。
第三步,输入set MINIO_SECRET_KEY=password命令,修改 SECRET-KEY。
第四步,输入minio.exe server F:\minio,启动minio。
以上流程结束,就成功啦~
import torch import torchvision.models as models # 加载预训练的 ResNet-50 模型 model = models.resnet50(pretrained=False) model.eval() # 示例输入 example_input = torch.randn(1, 3, 224, 224) # 将模型转换为 TorchScript script_model = torch.jit.trace(model, example_input) # 保存 TorchScript 模型 script_model.save("resnet_script_model.pt") import torch from torchvision.models import resnet # 构建相应的模型架构 model = resnet.resnet50() # 根据你的模型类型进行修改 # 加载 TorchScript 模型的参数权重 model.load_state_dict(torch.jit.load("resnet_script_model.pt").state_dict()) # 保存为.pth格式 torch.save(model.state_dict(), "resnet_model.pth") # 加载预训练的 ResNet 模型 # model = models.resnet50(pretrained=False) # 这里使用了一个预训练的 ResNet-50 模型,你可以根据自己的模型类型进行修改 # 加载模型权重 model.
哨兵模式详情 一、概述和实现逻辑
主从切换技术的方法是,当主服务器宕机后,需要手动把一台从服务器通过命令切换为主服务器,这就需要人工干预,还会造成一段时间内服务不可用。这不是一种值得推荐的方式,更多的时候,我们会优先考虑哨兵模式!!!
哨兵模式,是一个分布式系统:
通俗的讲,就是一种谋朝篡位的自动版,能够在后台监控主机是否故障,如果故障了,会根据投票自动将从服务器转换为主服务器。用于监控和管理Redis实例的高可用性。在Redis Sentinel中,哨兵实例之间通过PING和PONG消息进行通信。如果某个Redis主服务器不能被哨兵发现或者无响应,则该主服务器被视为已经失效。此时,哨兵需要选择一个可用的从服务器升级为主服务器,以确保Redis集群的高可用性,这个操作专业角度上讲叫做故障转移(failover)。
在进行故障转移时,哨兵需要确保多数派(majority)哨兵已经同意执行故障转移操作,这个多数派的大小(票数)通过参数quorum决定。例如:如果参数quorum设置为3,则至少需要3个哨兵实例同意执行故障转移操作!
当然为了保证quorum参数的正确性,一般都会将该参数设置成奇数。因为只有奇数个哨兵实例时才会有多数派的概念。如果设置成偶数,则可能出现多数派无法确定的情况,导致故障转移失败!
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。
二、工作原理图
哨兵的两个作用:
1、通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器
2、当哨兵检测到master宕机,会自动将slave切换成master,然后,通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会互相监控,这样就形成了多哨兵模式!
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover(故障转移)过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成称为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定的值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover故障转移操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程成为客观下线。 哨兵模式投票遵循的原则:
1、哨兵集群中的每个哨兵节点只有在自己判定主库下线时,才会给自己投票,而其他的哨兵节点会把票投给第一个来要票的请求,其后的请求都会被拒绝。
2、如果出现多个哨兵节点同时发现主库下线并给自己投票,导致投票选举失败,那么就会触发新一轮投票,直至成功。在选举过程中,遵循“少数服从多数”的原则,即不同的哨兵节点必须获得大多数成员的同
意,方可被选为Leader。
3、当大部分哨兵节点同意某个主节点死亡时,会宣布此主已死亡,并在所有哨兵之间广播这一消息。此时,被选为Leader的哨兵会开始完成故障转移的工作。
在故障转移的过程中,Leader会先尝试将被选为主节点的附属节点升级为主节点,但如果无法升级,则需要从可用节点中选择一个最终选举对象,让其他节点成为该节点的从属节点。Leader完成了主节点的选举后,让其
他节点开始向其同步数据,最终实现故障转移。
此外,哨兵集群的Leader选举成功与否还依赖于网络通信状况。如果网络拥塞,可能会导致选举失败,从而重新进行新一轮选举。
三、测试
现在的状态是一主二从!
1、在和Redis的配置文件统计的目录下,创建并配置哨兵sentinel.conf文件,注意文件名不能出错!
[root@guohui bin]# cd ghconfig/ [root@guohui ghconfig]# ls redis79.conf redis80.conf redis81.conf redis.conf [root@guohui ghconfig]# vim sentinel.conf 2、配置内容如下,现在的配置比较少,但是该配置是最基本也是最重要的!!!!!!
sentinel monitor myredis 127.0.0.1 6379 1 含义是:sentinel(哨兵) monitor(监控) 主机名称(随便起) host(主机ip) port(端口号) 1(代表如果主机挂了,哨兵可以投票选举某个从机为主机) 3、启动哨兵
启动命令和启动Redis服务一样,通过配置文件来启动
redis-sentinel ghconfig/sentinel.conf 实例:
[root@guohui ghconfig]# cd .. [root@guohui bin]# redis-sentinel ghconfig/sentinel.conf 7131:X 12 Apr 2023 10:25:41.
yolo车距
订阅车距专栏获得源码:https://blog.csdn.net/m0_68036862/category_12294299.html 目录
一、点云处理的挑战与深度学习方法
二、点云处理在车辆测距中的应用:PointNet、PointCNN等模型
1.PointNet
2.PointCNN
三、实际案例分析:激光雷达测距在实际场景中的应用
1.数据准备
2.训练模型
3.模型评估与可视化
四、结论:总结点云处理在车辆测距中的优势与局限性
随着自动驾驶技术的迅速发展,激光雷达(LiDAR)成为了无人驾驶汽车领域中不可或缺的一项关键技术。激光雷达通过发射激光束并接收反射回的激光信号,可以实时生成周围环境的三维点云数据。然而,点云数据的处理具有挑战性,如何高效、准确地利用这些数据对车辆周围环境进行感知和测距成为了一个重要课题。本文将探讨激光雷达与深度学习相结合的点云处理方法在车辆测距中的应用,以及如何使用Python编写代码实现这些方法。
一、点云处理的挑战与深度学习方法 点云处理的挑战主要来自两个方面:首先,点云数据是无序的,其表达形式不如图像数据那样规整;其次,点云数据具有不同的密度和分辨率,这给处理带来了一定的困难。为了解决这些问题,研究人员开始尝试使用深度学习技术来处理点云数据。深度学习可以自动学习数据的特征表示,从而实现高效的点云处理。
二、点云处理在车辆测距中的应用:PointNet、PointCNN等模型 1.PointNet PointNet是一种针对点云数据的深度学习模型。它通过使用多层感知器(MLP)和全局池化层来学习点云数据的特征表示。下面是一个简单的PointNet模型实现:
import tensorflow as tf from tensorflow.keras.layers import Dense, Input, BatchNormalization, Conv1D, GlobalMaxPooling1D def pointnet(input_shape=(None, 3)): inputs = Input(shape=input_shape) x = Conv1D(64, 1, activation='relu')(inputs) x = BatchNormalization()(x) x = Conv1D(128, 1, activation='relu')(x) x = BatchNormalization()(x) x = Conv1D(1024, 1, activation='relu')(x) x = BatchNormalization()(x) x = GlobalMaxPooling1D()(x) x = Dense(512, activation='relu')(x) x = Dense(256, activation='relu')(x) outputs = Dense(3, activation='softmax')(x) model = tf.
1.概念 Service-Oriented Architecture(SOA,面向服务的架构)和微服务是两种软件架构风格,它们都致力于构建灵活、可扩展、易于维护的分布式系统。以下是它们的主要区别和特点:
Service-Oriented Architecture(SOA):
定义:
SOA是一种软件设计和架构模式,通过将应用程序的功能划分为独立的、可重用的服务来实现系统的组件化。SOA强调面向服务的开发,其中服务是一种可独立调用的、自包含的功能单元。 服务通信:
通常使用SOAP(Simple Object Access Protocol)或RESTful协议进行服务之间的通信。服务之间的通信可能更为重量级,适用于企业级系统。 数据交互:
服务之间的数据通常是基于XML的,使用XML或JSON进行信息交换。服务的接口和契约是通过WSDL(Web Services Description Language)来定义的。 部署:
通常部署在大型的应用服务器上,服务的管理和编排较为复杂。常见的服务容器包括Java EE(Enterprise Edition)和.NET。 一体化系统:
SOA更多地关注整个企业级系统的一体化,强调中央的服务注册和发现。 微服务:
定义:
微服务是一种架构风格,将应用程序划分为一组小型、自治的服务。微服务强调每个服务都可以独立开发、部署、扩展和替换。 服务通信:
通常使用轻量级的RESTful协议进行服务之间的通信。服务之间的通信更为轻量级,适用于敏捷和快速开发的场景。 数据交互:
微服务通常使用JSON进行数据交互,也可以使用其他轻量级的数据格式。每个服务的接口和契约相对简单,定义清晰。 部署:
每个微服务可以独立部署,采用容器化技术如Docker,也可使用无服务器架构。常见的服务容器包括Docker、Kubernetes等。 分布式系统:
微服务关注系统的分布式特性,服务之间的通信需要考虑网络延迟、失败恢复等问题。微服务架构更适用于快速演化和敏捷开发的场景。 总体而言,SOA更侧重于整体企业系统的一体化,而微服务更侧重于小型、自治的服务,强调松耦合和独立性。选择SOA还是微服务取决于项目的需求、规模和团队的实际情况。
2.最佳实践 SOA(Service-Oriented Architecture)和微服务是两种不同的架构风格,它们在设计和实施时有一些最佳实践可以帮助确保系统的稳定性、可维护性和可扩展性。
SOA 的最佳实践:
明确的服务边界:定义清晰的服务边界,确保每个服务有独立的责任和功能。
标准化服务接口:使用标准的接口规范(如WSDL)定义服务的接口,确保易于理解和集成。
服务的可重用性:设计可重用的服务,使其能够在多个应用程序中被共享和调用。
强调中央化的服务管理:使用服务注册表和服务发现机制,确保中央的服务管理和监控。
数据交换标准:使用标准的数据交换格式(如XML)以确保不同服务之间的数据兼容性。
事务管理:实施分布式事务管理,确保在服务调用过程中的一致性。
微服务的最佳实践:
单一责任原则:每个微服务应专注于单一的业务功能,确保其职责清晰明确。
去中心化的数据管理:每个微服务应该有自己的数据存储,避免共享数据库,实现数据隔离。
服务的自治性:每个微服务应该是独立部署和升级的,不影响其他微服务的正常运行。
松耦合:通过轻量级的通信机制(通常是RESTful API)实现微服务之间的松耦合。
弹性设计:实施弹性设计,处理高负载、故障恢复、自动伸缩等情况。
服务治理和监控:使用服务注册和发现机制,实现微服务的服务治理和监控。
分布式日志和跟踪:使用分布式日志和跟踪工具,方便在微服务架构中进行故障排查。
容器化部署:使用容器技术(如Docker)对微服务进行封装和部署,确保环境的一致性。
适度的服务拆分:根据业务需求和团队规模适度划分微服务,避免微服务过于庞大或过于细小。
API网关:使用API网关来处理对外部的统一访问,加强对请求的安全性和监控。
总体而言,SOA和微服务的实践原则有一些相似之处,但在具体设计和实施时需要考虑到各自的特点和目标。选择合适的架构风格应该根据项目需求、组织结构和技术栈的实际情况进行权衡。
3.框架推荐 Service-Oriented Architecture(SOA)和微服务是一种架构风格,它们并不依赖于具体的框架,而是关注于组织和设计服务的方式。然而,有一些框架和工具可以用于实现和简化这两种架构的开发和管理。以下是一些在实践中广泛使用的框架:
SOA 框架:
Apache Axis2:一个基于Java的开源的SOAP框架,用于构建Web服务。
Microsoft WCF (Windows Communication Foundation):用于构建分布式应用程序和服务的.
效果 下图则启动成功,此时在浏览器访问127.0.0.1:8000可以看到本机监控画面
1、下载webrtc-streamer 地址:https://github.com/mpromonet/webrtc-streamer/releases
2、解压下载包 3、双击webrtc-streamer.exe启动服务 4、将下载包html文件夹下webrtcstreamer.js文件和html/libs文件夹下adapter.min.js文件复制到VUE项目public目录下。在index.html文件里引入这两个js文件 5.页面 中使用 注意:第三步在本机启动服务所以 new WebRtcStreamer(id,serverUrl)中URL传入127.0.0.1端口可
<template> <div> <div class="coTitle">视频</div> <video id='video' controls autoplay autobuffer muted preload='auto' style='width:90%; height: 290px; margin-left:5%;object-fit: fill;'> </video> </div> </template> <script> export default { name: 'index1', data() { return { webRtcServer: null } }, mounted() { //video:需要绑定的video控件ID //127.0.0.1:8000:启动webrtc-streamer的设备IP和端口,默认8000 this.webRtcServer = new WebRtcStreamer('video', 'http//127.0.0.1:8000') //需要查看的rtsp地址 this.webRtcServer.connect('rtsp://user:password@ip:port/cam/realmonitor?channel=1&subtype=0') //rtsp://user:password@ip:port/h264/ch1/main/av_stream--海康 }, beforeDestroy() { this.webRtcServer.disconnect() this.webRtcServer = null }, } </script> <style scoped></style> 6、运行项目可查看监控视频播放效果 文章参考链接:https://blog.
文章目录 方法一:使用转换函数方法二:使用 LPSTR( LPCTSTR content) 函数方法三:使用 (const char *)方法四:将字符集改为"使用多字节字符集"使用Unicode字符集的其他报错问题1. 无法将参数 1 从“const char [13]”转换为“CString”2. 无法将参数 1 从“const char [2]”转换为“wchar_t”3. 不存在从 "const char*转换到"ATL:uCStringT<wchar_t StrTraitMFC <wchar_t, ATL:.ChTraitsCRT<wchar t>>>”的适当构造函数4. 不存在从"CString”到“LPCSTR”的适当转换函数 方法一:使用转换函数 #include <string> #include <cstdlib> using namespace std; 以上是需要在MFC工程中添加的头文件 string CStringToString(CString cstr) { string str; setlocale(LC_ALL,"chs"); wchar_t wch[255]; char temp[255]; wcscpy(wch,cstr.GetString()); wcstombs(temp,wch,254); str.append(temp); return str; } 参考文章:https://www.cnblogs.com/walccott/p/4957114.html
方法二:使用 LPSTR( LPCTSTR content) 函数 方法三:使用 (const char *) 方法四:将字符集改为"使用多字节字符集" 使用Unicode字符集的其他报错问题 1. 无法将参数 1 从“const char [13]”转换为“CString” 加 CString() 括起来就行
为优化淘宝带宽成本,我们在网关 SDK(Java)统一使用 ZSTD 替代 GZIP 压缩以获取更高的压缩比,从而得到更小的响应包。具体实现采用官方推荐的 zstd-jni 库。zstd-jni 会调用 zstd 的 c++ 库。
背景
在性能压测和优化过程中,遇到了以下三个问题:
GC 次数不变,但耗时翻倍
进程内存泄漏,极限情况下会出现 OOM Killer 杀掉进程的情况
Netty 堆外内存泄漏(在优化问题 1 时引入)
下面我会从这三个问题展开,分享排查、解决问题的思路和过程。
GC 优化
▐ 【GC 耗时翻倍问题】现象 在我们预期中,使用 ZSTD 压缩,在大包场景下(20KB 以上),不仅能够获得比 GZIP 更高的压缩比;同时压缩性能也应有一定优化,具体优化程度取决于业务特征,但至少不会有性能劣化。
但实际性能压测发现相比于同级别的 Netty GZIP,ZSTD 压缩下,GC 次数不变,但耗时几乎翻倍,导致最终应用表现为几乎无任何性能优化,甚至影响 RT(CMS 下)。
▐ 【GC 耗时翻倍问题】分析 我们的 ZSTD 压缩是通过 JNI 实现,流程是将堆内数据拷贝到堆外压缩,再将拷回堆内。
使用 JNI 会在一定程度上影响 GC 的效率,这是我们已知的,但是耗时翻倍超出了我们的预期。因此我们尝试分析压缩的执行流程。
JDK 22 中通过在 G1 中实现 region pinning 来减少延迟,以在 JNI 执行期间无需禁用 GC,详见 JEP 423: Region Pinning for G1(地址:https://openjdk.
【华为_安全】防火墙IPsec双机实验 1. 前言2. 拓扑3. 需求4. 解法4.1 思路总部IP-Link双机热备IPsec路由部署 分公司(Fw3 动态公网IP)IPsecIP-Link路由部署 4.2 参考命令Fw1Fw2Fw3Fw4ISP1ISP2ISP3ISP4NAT-Device 4.3 故障测试FW1正常时PC1测试 isp1链路故障模拟关闭ISP1接口Fw1成为备墙Fw2成为主墙PC1测试 isp1链路故障恢复恢复ISP1接口Fw1成为主墙Fw2成为备墙PC1测试 4.4 流量走向诉求描述 1. 前言 学习华为防火墙IPsec双机实验记录
ensp拓扑链接:拓扑
防火墙登录账号都为admin
密码为Huawei@123
2. 拓扑 总部:
两台防火墙 采用双机部署,分别连接到ISP1、ISP2
总部两台防火墙的 ISP1 出口是 G0/0/3,连接 ISP2 的出口是 G0/0/5,缺省情况下,流量走 FW1 的 G0/0/3 接口
两台防火墙 作为内网用户的上网网关
两台防火墙 需要基于双机双出口与两个分公司分别建立 IPSec VPN。
分公司1:
路由器NAT-Device作为NAT设备,连接到ISP3
出口防火墙Fw3作为内网用户的上网网关,以及与总部对接IPSec VPN。
分公司2:
出口防火墙Fw4连接到ISP4,作为内网用户的上网网关,以及与总部对接IPSec VPN。
3. 需求 链路故障:
FW1连接 ISP1 链路故障,但是 ISP1 未故障,流量走 FW2 的 G0/0/3;FW1 连接 ISP1 链路未故障,但是 ISP1 故障,流量走 FW2 的 G0/0/5;FW1 连接 ISP1 链路恢复,ISP1 恢复,流量走 FW1 的 G0/0/3; 设备故障:
文章目录 一、知识点一二、将文件间的编译依存关系降至最低三、接口类 一、知识点一 将函数声明为内联一共有两种方法,一种是为其显式指定inline关键字,另一种是直接将成员函数的定义式写在类中,如下所示:
class Person { public: ... int Age() const { return theAge; } // 隐式声明为 inline ... private: int theAge; }; 在inline诞生之初,它被当作是一种对编译器的优化建议,即将“对此函数的每一个调用”都以函数本体替换之。但在编译器的具体实现中,该行为完全被优化等级所控制,与函数是否内联无关。
在现在的 C++ 标准中,inline作为优化建议的含义已经被完全抛弃,取而代之的是“允许函数在不同编译单元中多重定义”,使得可以在头文件中直接给出函数的实现。
在 C++17 中,引入了一个新的inline用法,使静态成员变量可以在类中直接定义:
class Person { public: ... private: static inline int theAge = 0; // since C++17 }; 在之前的C++标准中,静态变量需要在类外部进行初始化。
二、将文件间的编译依存关系降至最低 C++ 坚持将类的实现细节放置于类的定义式中,这就意味着,即使你只改变类的实现而不改变类的接口,在构建程序时依然需要重新编译。这个问题的根源出在编译器必须在编译期间知道对象的大小,如果看不到类的定义式,就没有办法为对象分配内存。也就是说,C++ 并没有把“将接口从实现中分离”这件事做得很好。
为了更好地将类中接口的定义和实现分割开来,我们可以实现两个类,一个类负责暴露接口,一个类负责接口的具体实现:
// person.hpp 负责声明类 class PersonImpl; class Person { public: Person(); void Print(); ... private: std::shared_ptr<PersonImpl> pImpl; }; // person.
第一题:一条sql执行过长的时间,你如何优化,从哪些方面?
答:1、查看sql是否涉及多表的联表或者子查询,如果有,看是否能进行业务拆分,相关字段冗余或者合并成临时表(业务和算法的优化)
2、涉及链表的查询,是否能进行分表查询,单表查询之后的结果进行字段整合
3、如果以上两种都不能操作,非要链表查询,那么考虑对相对应的查询条件做索引。加快查询速度
4、针对数量大的表进行历史表分离(如交易流水表)
5、数据库主从分离,读写分离,降低读写针对同一表同时的压力,至于主从同步,MySQL有自带的binlog实现 主从同步
6、explain分析sql语句,查看执行计划,分析索引是否用上,分析扫描行数等等
7、查看mysql执行日志,看看是否有其他方面的问题
第二题:深入理解CAP
CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)这三个要素最多只能同时实现两点,不可能三者兼顾。分布式系统肯定优先保证P,多数时候是在C和A之间做权衡选择!
C:各个节点查询的数据都一致;
A:所有节点尽量可用;
P:节点之间无法通信;
AP架构
向一个节点A写入数据成功后,立刻给客户端响应写成功的信号。
如果此时集群节点之间网络断开了,由于其可用性,其他节点仍然提供服务,但是A节点的数据还未写入到其他节点,当访问除A之外的其他节点时,就会出现数据不一致的问题,当网络恢复后,才会通过心跳保证最终一致性!
CP架构
在向一个节点A写入数据成功后,并不是马上给客户端响应写成功的信号,而是等待数据同步到其他节点后(个数取决于配置),才响应客户端,表示此次写数据成功了!这在一定程度上保证了数据一致性。为了防止数据混乱,写数据时只允许往Leader节点写,读数据时可以从所有节点读取!
CP架构下具有特殊的Leader - Flower机制,当发生网络分区时,非Leader分区下的节点会变成不可用,重新进入选举状态。
第三题:双十一秒杀高可靠如何实现?
Sentinel承接了阿里10年的促销场景,利用:流量控制(通过设置QPS来控制),容错(熔断就是切断坏路,让后续新流量再走这个坏路),降级(备选B角,走了try-cath的机制,),三板斧解决高可靠。熔断机制:通过滑动时间窗口实现的,对前一段时间的错误比例来设置熔断点。
第四题:分布式事务问题如何解决?
Seata:服务端也是通过安装和配置来实现,使用很简单,实现了事务协调功能,需要加一个依赖包,然后加一个注解@globalTranscational, AT模式,是最推荐的一种,举例:Seata如何协调订单和库存?要求同时成功或者失败。一阶段:订单和库存,都先做回滚日志记录在本地事务中,二阶段:如果有一个失败,通过回滚日志来回到回到初始。
第五题:nacos和zookeeper是如何防止脑裂的?
集群的脑裂通常是发生在集群之间通信不可达(分区)的情况下,一个大集群会分裂成不同的小集群,小集群中又各自选举出自己的master节点,导致原先的集群出现多个master节点对外提供服务的情况!
leader选举时,要求节点获取到的投票数量 > 总节点数量/2,有了这个选举原则,当发生网络分区时,无论如何最多只有一个小集群选出leader,避免集群发生脑裂。
第六题目:Redis为什么单线程还很快?
第七题:Spring Cloud 和dubbo区别?
1)服务调用方式
dubbo是RPC
SpringCloud采用Rest Api
2)注册中心
dubbo 是nacos、zookeeper
SpringCloud是eureka,也可以是nacos、zookeeper
3)服务网关
dubbo本身没有实现,只能通过其他第三方技术整合,
SpringCloud有Zuul路由网关,作为路由服务器,进行消费者的请求分发,springcloud支持断路器,与git完美集成配置文件支持版本控制,事物总线实现配置文件的更新与服务自动装配等等一系列的微服务架构要素。
第八题:线程间是怎么通信的,通过调用几个方法来交互的?
线程是通过wait , notify等方法相互作用进行协作通信;
wait()方法使得当前线程必须要等待,直到到另外一个线程调用notify()或者notifyAll()方法唤醒
wait()和notify()方法要求在调用时线程已经获得了对象锁,因此对这两个方法的调用需要在 synchronized修饰的方法或代码块中。
Wait,notify,notifyAll都必须在synchronized修饰的方法或代码块中使用,都属于Object的方法,可以被所有类继承,都是final修饰的方法,不能通过子类重写去改变他们的行为
第十题:SpringMVC工作流程?
1.用户请求旅程的第一站是DispatcherServlet。
2.收到请求后,DispatcherServlet调用HandlerMapping,获取对应的Handler。
3.如果有拦截器一并返回。
4.拿到Handler后,找到HandlerAdapter,通过它来访问Handler,并执行处理器。
5.执行Handler的逻辑。
6.Handler会返回一个ModelAndView对象给DispatcherServlet。
7.将获得到的ModelAndView对象返回给DispatcherServlet。
8.请求ViewResolver解析视图,根据逻辑视图名解析成真正的View。
9.返回View给DispatcherServlet。
10.DispatcherServlet对View进行渲染视图。
11.DispatcherServlet响应用户。
第十一题:阐述设计模式的责任链?
文章目录 一、进程相关内容1.1 查看进程启动时间 和 运行时间1.2 Linux 进程常见状态(R、S、D、T、Z、X)1.3 如何查看 ps 命令支持哪些参数 一、进程相关内容 1.1 查看进程启动时间 和 运行时间 查看进程启动时间
命令:ps -eo pid,lstart,cmd某个进程:ps -eo pid,lstart,cmd | grep udhcp 查看进程运行时间
使用 ps -p <进程ID> -o etime 来查看某个进程运行的时间。
示例:ps -p 1384 -o etime 内容见上图 其他参考:linux查看进程启动时间
ps -eo lstart 启动时间 ps -eo etime 运行多长时间. ps -eo pid,lstart,etime | grep 5176 1.2 Linux 进程常见状态(R、S、D、T、Z、X) R (Running)运行状态:正在运行或在运行队列中等待执行的进程。S (Sleeping)睡眠状态:处于休眠状态或等待某个事件的进程。当进程被唤醒后,它将切换到R状态。D (Disk sleep)磁盘睡眠状态:等待磁盘I/O操作完成的进程。不可中断睡眠(深度睡眠,不可以被唤醒,通常在磁盘写入时发生)T (Stopped)停止状态:进程被停止或收到了SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU信号而暂停执行。Z (Zombie)僵尸状态:已经终止但是父进程还没有回收其资源的进程。X (Dead)死亡状态:进程已经终止。 参考资料
Linux进程状态(ps stat)之R、S、D、T、Z、XLinux操作系统中进程的七种状态 1.3 如何查看 ps 命令支持哪些参数