Hadoop大数据应用:NFS网关 连接 HDFS集群

目录 一、实验 1.环境 2.NFS网关 连接 HDFS集群 3. NFS客户端挂载HDFS文件系统 二、问题 1.关闭服务报错 2.rsync 同步报错 3. mount挂载有哪些参数 一、实验 1.环境 (1)主机 表1 主机 主机架构软件版本IP备注hadoop NameNode (已部署) SecondaryNameNode (已部署) ResourceManager(已部署) hadoop 2.7.7192.168.204.50 node01 DataNode(已部署) NodeManager(已部署) hadoop 2.7.7192.168.204.51node02 DataNode(已部署) NodeManager(已部署) hadoop 2.7.7192.168.204.52node03 DataNode(已部署) NodeManager(已部署) hadoop 2.7.7192.168.204.53nfsgateway Portmap Nfs3 hadoop 2.7.7192.168.204.56node04 nfs-utils192.168.204.54nfs客户端node05 nfs-utils192.168.204.55nfs客户端 (2)查看jps hadoop节点 [root@hadoop hadoop]# jps node01节点 node02节点 node03节点 2.NFS网关 连接 HDFS集群 (1) 修改主机名 [root@localhost ~]# hostnamectl set-hostname nfsgateway [root@localhost ~]# bash (2)配置代理用户 nfsgateway节点

Dropping Balls(UVA 679)

网址如下: Dropping Balls - UVA 679 - Virtual Judge (vjudge.net) (第三方网站) 二叉树 别说了,我只会模拟,最后用时530ms 结果算法书给出了一个优化的解法: 因为小球要么往左,要么往右,根据到这个点有几个小球可以推断出当前点的状态,根据要求的第几个小球可以推断在这个点有多少个球往左走了,多少个球往右走了 这样可以根据 I 直接推断出第 I 个的动向,配合D直接算出答案 用时20ms 代码如下: #include<cstdio> int main(void) { int l; scanf("%d", &l); for(int i = 0; i < l; i++) { int D, I; scanf("%d%d", &D, &I); int k = 1, d = 1; while(d++ < D) { if(I % 2) k = k * 2; else k = k * 2 + 1; I = (I + 1) / 2; } printf("

市场复盘总结 20240314

仅用于记录当天的市场情况,用于统计交易策略的适用情况,以便程序回测 短线核心:不参与任何级别的调整,采用龙空龙模式 一支股票 10%的时候可以操作, 90%的时间适合空仓等待 二进三: 进级率中 25% 最常用的二种方法: 方法一:指标选股找强势股 select * from dbo.ResultAll where 入选类型 like '%指标选股%' and 入选日期='20240314'; 方法二:趋势选股法,找龙头 1、最低价持续3日上涨 2、均价持续3日上涨 3、收盘价持续3日上涨 4、最高价持续3日上涨 5、开盘价持续3日上涨 6、均线成发散形态 select * from dbo.ResultAll where 入选类型 like '%趋势选股法%' and 入选日期='20240314'; 空 五步选股法: SELECT CODE ,成交额排名 ,净流入排名 ,代码 ,名称 ,DDE大单金额 ,涨幅 ,主力净额 ,DDE大单净量 ,CONVERT(DATETIME, 最后封板, 120) AS 最后封板 ,涨停分析 ,_3日涨幅百分比 ,连板天 ,封单额 ,封单额排名 ,DDE散户数量 ,总金额 ,获利盘 ,开盘金额 ,开盘涨幅 ,量比 from dbo.全部A股20240314_ALL where 开盘涨幅>1 and 开盘涨幅<5 and 开盘金额>100 and 开盘金额<5000 and 量比>1 and 量比<5

[论文精读]Dynamic Coarse-to-Fine Learning for Oriented Tiny Object Detection

论文网址:[2304.08876] 用于定向微小目标检测的动态粗到细学习 (arxiv.org) 论文代码:https://github.com/ChaselTsui/mmrotate-dcfl 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 1. 省流版 1.1. 心得 (1)为什么学脑科学的我要看这个啊?愿世界上没有黑工 (2)最开始写小标题的时候就发现了,分得好细啊,好感度++ (3)作为一个外行人,这文章感觉提出了好多东西 1.2. 论文总结图 2. 论文逐段精读 2.1. Abstract ①Extreme geometric shapes (tiny) and finite features (few pixels) of tiny rotating objects will cause serious mismatch (inaccurate positional prior?) and imbalance (inaccurate positive sample features?) issues ②They proposed dynamic prior and coarse-to-fine assigner, called DCFL posterior adj.在后部的;在后面的 n.臀部;屁股 2.2. Introduction ①Oriented bounding box greatly eliminates redundant background area, especially in aerial images

JVM基础篇

什么是JVM java虚拟机 JVM的功能 1.解释和运行 对字节码文件中的指令,实时的解释成机器码,让计算机执行 2.内存管理 自动为对象、方法等分配内存 自动的垃圾回收机制,回收不再使用的对象(c++不会自动回收,相当于降低了编程的下限) 3.即时编译(JIT) 对热点代码进行优化,提升执行效率 java需要实时解释是为了不同平台的兼容性,然而由于需要实时编译,所以性能方面比不上c++,所以就需要即时编译 即时编译的过程 把热点代码(就是频繁出现的代码)放到内存,这样下次就不用再编译了,提高性能。 java虚拟机的组成 1.类加载器(加载字节码文件到内存) 2.运行时的数据区域(JVM管理的内存) 负责管理jvm使用到的内存,比如对象的创建和销毁 3.执行引擎(即时编译器、解释器、垃圾回收器等)(将字节码内的指令解释成机器码,同时视同JIT即时编译器优化性能) 4.本地接口(调用本地编译的方法,比如c/c++实现的方法 native方法) 字节码文件的组成 jclasslib查看字节码文件 字节码文件的组成 魔数:java字节码文件,将文件头称为魔数 主副版本号:jdk1.2是46 之后每升级一个大版本就+1 比如jdk1.8就是46+6 52 主版本号作用就是判断当前字节码的版本和运行时的jdk是否兼容 常量池:避免相同的内容重复定义,节省空间 类的生命周期 五个阶段:加载、链接、初始化、使用、卸载 加载阶段:第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息,第二步类加载器加载完类以后,java虚拟机就会把字节码中的信息放到一个内存区里面(就是方法区),第三步生成一个INstanceklass对象,保存类的所有信息,里面还包含实现特定功能的信息如多态信息。 第四步:同时,java虚拟机还会在堆中生成一份与方法区中数据类似的java.lang.class对象。 作用是在java代码中去获得类的信息一级存储静态字段的数据。 问:既然都方法区都有信息了,为什么还要在堆区存储信息? 答:方法区中的instanceklass是用c++实现的,对于我们java程序是不好直接操作的。所以我们要转换为java.lang.class对象才好操作。并且堆区的字段少于instanceklass,不是所有字段都需要访问的,所以要控制开发者的访问范围 连接阶段:有三个小阶段 验证、准备。解析。 验证:检验程序的内容是否符合java虚拟机的规范 准备:准备阶段为静态变量(static)分配内存并设置初始值(这里的初始值是指默认值 不是你赋的值 比如int的初始值就是0)。 但是如果是final修饰的静态变量的话,在准备阶段就会赋你给定的值,不用等到初始化阶段。 解析阶段:将常量池的符号引用替换成直接引用。 符号引用:在字节码文件中使用编号来访问常量池的内容。 直接引用:不再使用编号,直接使用内存的地址进行访问具体数据 初始化阶段:会执行静态代码块中的代码,并为静态变量赋值。 从字节码角度分析就是执行字节码文件中clinit部分的字节码指令 初始化阶段不一定存在 出现继承的初始化阶段: final修饰的变量如果赋值的内容需要执行指令才能出结果,那么就会执行clinit指令进行初始化 类加载器 java虚拟机提供给应用程序去实现获得类和接口字节码数据的技术 类加载器分为两类 一类是java代码实现 一类是java虚拟机底层源码实现的 类加载器在jdk8和8之后的差别很大 启动类加载器:用于加载java安装目录/jre/lib下的类文件 可以帮我们扩展我们要用的核心类 1.放入jre/lib进行扩展(不推荐使用) 2.使用参数进行扩展 扩展类加载器:用于加载/jre/lib/ext下的类文件 类似于启动类加载器 我们也可以通过扩展类加载器去加载用户的jar包 应用程序类加载器:用于加载classpath下的类文件 类加载器的双亲委派机制(重点) 这东西的核心就是解决一个类到底由谁加载的问题(有多个类加载器) 作用:

pytorch之诗词生成5--train

先上代码: import tensorflow as tf from dataset import PoetryDataGenerator, poetry, tokenizer from model import model import settings import utils class Evaluate(tf.keras.callbacks.Callback): """ 在每个epoch训练完成后,保留最优权重,并随机生成settings.SHOW_NUM首古诗展示 """ def __init__(self): super().__init__() # 给loss赋一个较大的初始值 self.lowest = 1e10 def on_epoch_end(self, epoch, logs=None): # 在每个epoch训练完成后调用 # 如果当前loss更低,就保存当前模型参数 if logs['loss'] <= self.lowest: self.lowest = logs['loss'] model.save(settings.BEST_MODEL_PATH) # 随机生成几首古体诗测试,查看训练效果 print(tokenizer.id_to_token((3))) print(tokenizer.id_to_token(2)) print(tokenizer.id_to_token(1)) print(tokenizer.id_to_token(0)) for i in range(settings.SHOW_NUM): print(utils.generate_random_poetry(tokenizer, model)) # 创建数据集 data_generator = PoetryDataGenerator(poetry, random=True) # 开始训练 model.fit_generator(data_generator.for_fit(), steps_per_epoch=data_generator.

Spring Boot简析

一 什么是Spring Boot Spring Boot是一个简化Spring应用程序开发的框架,提供了自动化配置、快速启动和丰富的功能模块,使开发者能够更快速、更便捷地构建和部署Spring应用程序。 1.1 什么是spring应用程序 Spring应用程序是基于Spring框架开发的应用程序。Spring框架是一个开源的Java应用程序框架,用于开发企业级Java应用程序。它提供了一系列的功能和特性,使得开发人员可以更轻松地构建可维护、灵活和可扩展的应用程序。 Spring应用程序通常是使用Spring框架的核心容器来管理和组织应用程序的各个组件,包括依赖注入(Dependency Injection)、面向切面编程(Aspect-Oriented Programming)、事务管理等。Spring框架还提供了一系列的模块和扩展,用于支持不同类型的应用程序开发,如Web开发、数据访问、安全等。 Spring应用程序可以是传统的基于JavaEE的Web应用程序,也可以是基于Spring Boot的微服务应用程序。无论是哪种类型的应用程序,使用Spring框架可以提供更高的开发效率、更易于维护和扩展的应用程序架构,并且可以在不同的环境中灵活地部署和运行。 1.2 Spring Boot自动化配置通过什么实现 Spring Boot的自动化配置是通过条件化的配置和条件注解来实现的。 一方面,Spring Boot会根据应用程序的类路径以及已经存在的Spring Bean来自动配置应用程序的各个组件和功能。它会根据一系列的默认规则和条件,自动创建和配置Spring Bean,加载配置文件,设置属性等。 另一方面,Spring Boot提供了一系列的条件注解,例如@ConditionalOnClass、@ConditionalOnBean、@ConditionalOnProperty等。这些注解通过在配置类或配置方法上添加,指定条件,只有当满足指定条件时,相应的配置才会生效。这样,开发人员可以根据需要,通过添加和配置这些条件注解来控制自动化配置的生效和执行。 此外,Spring Boot还提供了一些自定义配置的方式,例如通过application.properties或application.yml配置文件进行配置,通过@EnableAutoConfiguration注解引入自动配置类等。 二 Spring Boot的发展历程 Spring Boot的开发历程可以追溯到2013年,当时由Spring团队推出了Spring Boot项目。该项目的初衷是简化传统的Java开发模式,提供一种快速构建和部署Java应用程序的方式。 在过去,开发Java应用程序需要手动配置各种不同的框架和库,这使得开发过程复杂且耗时。为了解决这个问题,Spring Boot引入了自动配置和约定优于配置的原则。 自动配置是Spring Boot的一个重要特性,它根据应用程序的类路径及已有的依赖信息,自动设置框架和库的配置。这样,开发人员无需手动编写大量的配置代码,可以快速启动一个可用的应用程序。 除了自动配置,Spring Boot还提供了许多其他功能,如嵌入式Web服务器、健康检查、监控、打包工具等。这些功能使得开发人员可以更轻松地构建和管理应用程序。 随着时间的推移,Spring Boot逐渐成为Java开发领域热门的框架之一。它的开发和使用也得到了广泛的社区支持和贡献。目前,Spring Boot已经发展成为一个成熟且稳定的框架,被广泛应用于各种Java后端开发项目。 三 Spring Boot的特点 Spring Boot的特点包括: 1. 简化配置:Spring Boot提供了自动配置的功能,可以根据项目的需要自动配置相应的环境,减少了开发人员的配置工作量。 2. 内嵌服务器:Spring Boot可以内嵌Tomcat、Jetty等服务器,不需要额外安装和配置服务器环境。 3. 快速开发:Spring Boot提供了丰富的起步依赖,可以快速集成各种常用的功能模块,加快项目开发速度。 4. 微服务支持:Spring Boot可以很容易地构建和部署微服务架构的应用,支持使用Spring Cloud进行微服务的管理和治理。 5. 自动化管理:Spring Boot提供了一系列的配置管理和监控功能,可以方便地管理和监控应用的状态和性能。 6. 开箱即用:Spring Boot提供了丰富的开箱即用的特性,如健康检查、安全性、性能优化等,可以快速搭建可靠和高效的应用。 7. 开放式扩展:Spring Boot采用模块化的设计,可以方便地扩展应用的功能,集成第三方的库或框架。 四 Spring Boot的应用场景 Spring Boot适用于各种类型的应用程序开发,包括Web应用程序、RESTful API、批处理作业、微服务等。

『 Linux 』进程替换( Process replacement ) 及 简单Shell的实现(万字)

文章目录 🦄 进程替换🦩 execl()函数🦩 execlp()函数🦩 execle()函数🦩 execv()函数🦩 execvp()函数🦩 execvpe()函数🦩 execve()函数 🦄 简单Shell命令行解释器的实现🦩 大致框架与命令行提示符🦩 获取用户输入信息🦩 将缓冲区内的字符串进行分块🦩 分析并执行指令🦩 对cd命令进行处理🦩 简单Shell实现代码演示(供参考) 🦄 进程替换 在『 Linux 』Process Control进程控制(万字)-CSDN博客 中提到了些进程控制中的概念,但是在这篇文章当中对于进程替换的概念以及用法并没有完全; 在本篇文章中将对上篇文章中的进程替换的各个接口进行补充; 进程替换,按照字面意义上即为一个进程在运行过程当中替换为另一个进程; 在之前的博客当中可能提到过, 当一个程序被加载进内存当中时对应的内存会新生成一个对应的进程; 而在进程替换当中可以完美的对上面的理论进行一个反驳,即并不是每个程序加载到内存当中都会新生成一个对应的进程; 以该图为例,该图中一个正在执行的进程经过了进程替换,将磁盘中的程序的代码和数据加载到了被替换的进程对应的PCB结构体当中; 当然在物理内存当中需要对应的为该新载入的进程的数据代码开辟一块新的内存空间; 但实际上在进程地址空间来看的话也仅仅只是将对应的映射关系进行修改; 当新的程序代码数据被加载进物理内存时,随着进程逐渐发生替换,对应的原有的代码和数据也将渐渐被释放; 因为只是仅仅的发生映射关系的转换,故对应的PID等mm_struct内的数据都不会作修改; 在上篇文章中简单的使用了execl()进程替换函数进行了进程替换的演示; #include <unistd.h> #include <iostream> using namespace std; int main() { cout << "hello world1" << endl; cout << "hello world1" << endl; cout << "hello world1" << endl; printf("当前程序为myproc 且PID为:%d \n", getpid()); execl("./test_/mytest", "

力扣热题100_矩阵_48_旋转图像

文章目录 题目链接解题思路解题代码 题目链接 48.旋转图像 给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1: 输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] 输出:[[7,4,1],[8,5,2],[9,6,3]] 示例 2: 输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]] 输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]] 解题思路 1.初始化n,计算matrix矩阵长度 2.水平翻转(先判断列数,再往下循环行数) 3.对角线翻转 解题代码 class Solution: def rotate(self, matrix: List[List[int]]) -> None: n = len(matrix) for i in range(n // 2): for j in range(n): matrix[i][j], matrix[n-i-1][j] = matrix[n-i-1][j], matrix[i][j] for i in range(n): for j in range(i): matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] return matrix

Sqlserver 模糊查询中文及在mybatis xml【非中文不匹配查询】N@P2问题

问题 sqlserver模糊查询或相等,两者都无法查询。 百度方案解释 Like 后的N是表示unicode字符。获取SQL Server数据库中Unicode类型的数据时,字符串常量必须以大写字母 N 开头,否则字符串将转换为数据库的默认代码页(字符集编码),这可能导致字符串内容发生变化,无法识别。 在SQL界面中 select * from table where column like N'%文档%' 但是在mybatis这样就不好写了。 注意点 一定不要使用mybatis的where标签,否则mybatis会识别为N@P2 N后面必须用 ‘’ + #{queryColumn} 这种格式 模糊查询 select * from table where <if test="queryColumn != null and queryColumn != ''"> column like N'%'+#{queryColumn}+'%' </if> 相等查询 结合上面,我们发现N后面不能直接拼接#{queryColumn}参数,否则就会报错! select * from table where <if test="queryColumn != null and queryColumn != ''"> column = N''+#{queryColumn} </if>

【论文阅读】MoCoGAN: Decomposing Motion and Content for Video Generation

MoCoGAN: Decomposing Motion and Content for Video Generation 引用: Tulyakov S, Liu M Y, Yang X, et al. Mocogan: Decomposing motion and content for video generation[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2018: 1526-1535. 论文链接: [1707.04993] MoCoGAN: Decomposing Motion and Content for Video Generation 代码链接:GitHub - sergeytulyakov/mocogan: MoCoGAN: Decomposing Motion and Content for Video Generation 简介 视频中的视觉信号可以分为内容和运动。内容指定了视频中的对象,而运动描述了它们的动态。基于这一先验知识,我们提出了运动和内容分解的生成对抗网络(MoCoGAN)框架用于视频生成。所提出的框架通过将一系列随机向量映射到一系列视频帧来生成视频。每个随机向量由内容部分和运动部分组成。在内容部分保持固定的同时,运动部分被实现为一个随机过程。由于短视频剪辑中的内容通常保持不变,因此使用高斯分布对内容空间进行建模,并使用相同的实现来生成视频剪辑中的每一帧。从运动空间采样是通过循环神经网络实现的,在训练期间学习网络参数。为了以无监督的方式学习运动和内容的分解,引入了一种新的对抗性学习方案,利用图像和视频鉴别器。在几个具有挑战性的数据集上进行的广泛实验结果,以及与最先进方法的定性和定量比较,验证了所提出框架的有效性。此外,展示了MoCoGAN允许生成具有相同内容但不同运动的视频,以及具有不同内容但相同运动的视频。 首先,由于视频是执行各种动作的物体视觉信息的时空记录,因此生成模型除了学习物体的外观模型之外,还需要学习物体的合理物理运动模型。如果学习到的物体运动模型不正确,则生成的视频可能包含执行物理上不可能的运动的物体。其次,时间维度带来了巨大的变化。考虑一个人在进行深蹲运动时可以有的速度变化量。每种速度模式都会产生不同的视频,尽管视频中人类的外表是相同的。第三,随着人类进化到对运动敏感,运动伪影特别容易察觉。 我们认为,假设视频剪辑是潜在空间中的一个点,会不必要地增加问题的复杂性,因为具有不同执行速度的相同动作的视频由潜在空间中的不同点表示。此外,这种假设迫使每个生成的视频剪辑具有相同的长度,而真实世界视频剪辑的长度却各不相同。另一种(可能更直观、更有效)的方法是假设图像的潜在空间,并考虑通过遍历潜在空间中的点来生成视频剪辑。不同长度的视频片段对应于不同长度的潜在空间轨迹。 此外,由于视频是关于执行动作(运动)的对象(内容),因此图像的潜在空间应进一步分解为两个子空间,其中第一个子空间(content subspace)中一个点的偏差导致视频剪辑中的内容变化,第二个子空间(motion subspace)中的偏差导致时间运动。通过这种建模,具有不同执行速度的动作视频只会导致运动空间中轨迹的遍历速度不同。分解运动和内容可以更可控地生成视频过程。通过在固定运动轨迹的同时改变内容表示,我们可以获得不同物体执行相同运动的视频。通过在固定内容表示的同时改变运动轨迹,我们可以获得同一物体执行不同运动的视频,如图 1 所示。 Generative Adversarial Networks GANs由一个生成器和一个鉴别器组成。生成器的目标是生成类似于真实图像的图像,而鉴别器的目标是将真实图像与生成的图像区分开来。设 x x x 是从图像分布 p X p_X pX​中绘制的实数图像, z z z是 Z I ≡ R d Z_I ≡ R^d ZI​≡Rd 中的随机向量。让 G I G_I GI​ 和 D I D_I DI​ 成为图像生成器和图像鉴别器。生成器将$ z$ 作为输入并输出一个图像 x ~ = G I ( z ) \tilde { x } = G _ { I } ( z ) x~=GI​(z),该图像具有与 x x x 相同的支持。将 G I ( z ) G_I(z) GI​(z) 的分布记为 $p_{G_I} $。鉴别器估计从 p X p_X pX​ 绘制输入图像的概率。理想情况下,如果 x ∼ p X x ∼ p_X x∼pX​ ,则 D I ( x ) = 1 D_I(x) = 1 DI​(x)=1,如果 x ~ ∼ p ~ G I \tilde { x } \sim \tilde { p } _ { G _ { I } } x~∼p~​GI​​,则 D I ( x ~ ) = 0 D _ { I } ( \tilde { x } ) = 0 DI​(x~)=0。 G I G_I GI​ 和 D I D_I DI​ 的训练是通过求解:

C语言之指针(四)

一、前言 哈喽大家好,经过前三次的学习,我们已经了解到了指针的诸多概念,同时也分别从计算机内存、&符号、机器位数和野指针等多方面去研究指针,那么接下来,我们要研究的是关于指针在数组中的应用,在此也附上上一篇关于指针的文章,以便大家参考。C语言之指针(三)-CSDN博客 二、数组名的理解 我们在学习数组时,相信大家也学习过如下代码: #include<stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* a = arr; return 0; } 上述代码是将arr数组中的首地址放入了一个整形指针变量a中,在此,arr则代表的是数组的首元素地址,由代码可知: #include<stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* a = arr; printf("%p\n", arr); printf("%p\n", &arr[0]); printf("%p\n", a); return 0; } 运行结果如下: 我们发现数组名和首元素地址以及指针变量a所打印出的地址都是一样的,数组名就是首元素的地址(数组中第一个元素)。但是,需要注意的是,对于数组名就是首元素地址是正确的,不过却有两个例外: (1)sizeof(数组名):sizeof中单独存放数组名,这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。 (2)&(数组名):&(数组名)表示的是整个数组的地址,为了方便理解,我们用代码体现: #include<stdio.h> int main() { int arr[3] = { 1,2,3 }; int(*a)[3] = &arr; printf("%p\n", arr);//首元素地址 printf("%p\n", &arr);//整个数组的地址 printf("%p\n", &arr + 1);//数组地址+1的地址 printf("

从“手写病例”到“AI家庭医生”,人工智能大数据如何走进我们的生活?

编 辑:老彭 来 源:大数据架构师 彭友们好,我是老彭。最近“X疾病”肆虐,彭友们要小心啊,一定要保重身体。老彭去年就老去医院,不知道是不是“X疾病”闹的。 上周末我特意找国家卫健委沈剑峰沈博士请教,顺便叙叙旧,他给我们讲了很多很有意思的医学新进展。老彭现在转述给彭友们,让我们康康人工智能、大数据是如何赋能健康中国的。 病历数据的进化 早期的医学是不会给每个病人写病历、建档案的。原因很简单,没那个条件。 只有在做研究、遇到特殊病人、疾病(比如各类传染病)的时候才会详细记录在案。 那时候写的病历都是从医生的视角出发,记录问诊病人的病情。记录的形式也比较散乱,都是各自按自己的习惯记录。那时候不能叫“病历”,只能叫做“医历”,因为是“医生行医日志”。 在这个时候,就不得不提到大名鼎鼎的“梅奥诊所”。梅奥诊所在1901年迎来了一个重要的人:亨利·普拉莫。他做出了重大的改革: 1.从医生视角记录“医生行医日志”改为从病人视角记录“病人就医历史”; 2.所有医生记录的“医历”和“病历”都交给医院统一管理,并标准化,形成“综合性病历管理系统”。 从这个时候开始,所有去梅奥诊所就医的病人都会拥有一个写着自己名字的小本本,上面只有自己的就医记录。 但是这会带来一个问题:因为梅奥诊所非常出名,所以会有非常非常多的病人前去就医。很快,病历就堆满了梅奥诊所的档案室。翻找病历就成了一项非常耗时的工作,以至于病人挂号老半天,结果直到下班了都还没病历的尴尬境地。 然后,梅奥诊所就升级了病历系统。医生和工程师借鉴了“气动管道传输(Pneumatic Tube Transport)”的思路,打造了一个利用空中钢缆和滑槽组成的机械病历系统。 纽约气动管道传输系统,常用于传输信件 老彭没找到梅奥诊所的机械病历系统的照片,只找到了纽约气动管道传输系统的照片,各位凑合看吧。有哪位彭友找到了梅奥诊所机械病历系统的照片,可以发给我哈。 这种看上去很蒸汽朋克的手段,让梅奥诊所的效率远超其他医院。这种手段直到上世纪90年代才被电子病历取代。 电子病历示意 现在咱国家几乎所有的医院都会将病人的病历制作成电子病历,甚至是部分乡村医院。而我们现在买的病历本也成了贴打印版病历的粘贴本了。 病历电子化之后,好处多多,最基础的好处就是病历数据电子化,可以为后续的流程提供更加精准、便捷的基础数据。 电子病历技术解密: 以前想要研究病历数据,那得翻乱了,多费劲啊!现在可简单了。医生在电脑上把病人信息、检查数据、诊断数据、开药数据等信息按照一定的结构存到医院信息系统(Hospital Information System ,HIS)之后,无论是治疗还是做研究,就非常方便了。 电子病历的应用已经开始向跨院读取、互认发展,避免了以前换医院看病就得重新再做一遍检查的尴尬做法,不仅省钱,还方便。 这电子病历不仅做到了无纸化,还实现了数据共享,妙哇! 配药的智慧化 老彭小的时候,不管是看中医还是看西医,取药都是一件让人感觉很高深莫测的事情。 西医药袋 那时候无论中西医的医生开药,都是把各种看不懂的药分装在一个个的袋子里。区别是中医药袋很大,里面是各种炮制后的动植物,而西医药袋则很小,里是一粒粒的药丸。 但是最近我可是被医院取药的地方震惊了。最早我记得应该是在协和医院,看到一个很神奇的取药机器人,人不动,药柜子动,极大地提升了配药的时间。 但是后来,我陆续在其他医院看到了更高级的版本: 自动发药机 有了这个自动发药机,人和药柜子都不用动了,药品自动配好,直接传送到取药窗口。这个效率太牛了! 发药机部署图 自动发药机技术解密: 如上图所示,医生开完处方单之后,病人交完费就可以去扫码取药了。配药系统收到病人取药扫码信息后分配取药窗口(就是那台发药机给发药),然后对应的发药机收到配药指令,按照处方单开始配药,之后就哗啦一下全掉到取药窗口,药剂师检查一下就可以发药了。 这个数据流对于病人、医生和药剂师来说,完全无感,数据跑上跑下,药品一步到位,真滴是肥肠滴666! 治疗手段的进化 老彭初中的时候学习《扁鹊见蔡桓公》,当时就惊为天人。哪有看一眼就知道病人得了什么病的神奇术法。后来听了悬丝诊脉的故事,更是惊掉下巴,看都看不到,只拉一根线就能看病? 后来老彭爱了看光怪陆离的小说,最喜欢世外高人,他们总有种种神奇的手段,或是开坛做法,或是画符结印,就能消灾除厄,治病救人。 我一直以来对于医生治病救人的感官就是再高的医术,只要不是神仙手段,就得老老实实的上门看病。 后来因为工作原因,了解到中国的远程医疗已经非常完善了。一开始还是远程问诊,后来随着5G、手术机器人等技术的不断成熟,现在已经可以实现远程做手术了! 远程手术(左边是医生在操作,右边是机器人做手术) 5G的高带宽特性,能将手术现场的超高分辨率视频回传到千里之外,而低延迟特性能让医生和手术机器人的动作实时同步,从而实现超越距离限制的“神迹”! 如此这般神乎其神的手段,在我小时候还只能在神话小说里才能看到。实在是佩服佩服 远程手术技术解密: 医生端和病人端通过专网建立实时信号传输通道。病人端的手术机器人把高清摄像头拍摄的画面传输至医生端,医生通过操作台在千里之外指挥手术机器人进行手术。 手术机器人除了远程医疗功能之外,还拥有超大视野、超级灵活、消除震颤等一系列buff。 《人工智能赋能健康中国》 沈博士还跟老彭聊了很多很多案例,都出自由他主编,新鲜出版的《人工智能赋能健康中国》一书。 里面可不止上面提到的电子病历、自动发药机和远程医疗,还有人工智能家庭医生、智能采血机器人等13个案例。全文由一个报告+13个漫画故事组成,既专业权威、又深入浅出,我家娃都抱着啃得津津有味。 这本书的作者们可超级厉害,上面全是各大医院知名专家点评过审,挂号都挂不着的那种。甚至连画画的都是一线医生,博士起步的那种。 小彭很喜欢 老彭在这里帮沈博士打个广告,《人工智能赋能健康中国》绝对值得一看。 更多精彩: 医改缩影:医院绩效制度改革的思考 医改为什么必须要制度创新? 开放是最大的垄断-论中医、马斯克、得到和鸿蒙 排版 | 老彭 审校 | 老彭 主编 | 老彭

二叉搜索树、B-树、B+树

二叉搜索树 二叉查找树,也称为二叉搜索树、有序二叉树或排序二叉树,是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;任意节点的左、右子树也分别为二叉搜索树; 如果二叉查找树是平衡的则查找、插入的时间复杂度为O(logn)。如果二叉查找树完全不平衡则时间复杂度为O(n)。 中序遍历二叉搜索树可以获得关键字的递增序列 二叉搜索树的查找算法 在二叉查找树b中查找x的过程为: 若b是空树,则搜索失败,否则:若x等于b的根节点的值,则查找成功;否则:若x小于b的根节点的值,则搜索左子树;否则:查找右子树。 二叉搜索树的节点插入算法 向一个二叉搜索树b中插入一个节点s的算法,过程为: 若b是空树,则将s所指节点作为根节点插入,否则:若s->data等于b的根节点的值,则返回,否则:若s->data小于b的根节点的值,则把s所指节点插入到左子树中,否则:把s所指节点插入到右子树中。(新插入节点总是叶子节点) 二叉搜索树的节点删除算法 若待删除节点*p为叶子节点则直接删除即可若待删除节点*p只有左子树PL或右子树PR,则当*p是左子树(右子树)时直接令PL或PR成为其父节点*f的左子树(右子树)若待删除节点*p的左子树或右子树均不为空, 其一是令*p的左子树为*f的左/右(依*p是*f的左子树还是右子树而定)子树,*s为*p左子树的最右下的结点,而*p的右子树为*s的右子树;其二是令*p的直接前驱或直接后继替代*p,然后再从二叉查找树中删去它的直接前驱(或直接后继)。 AVL树 AVL树得名于它的发明者格奥尔吉·阿杰尔松-韦利斯基和叶夫根尼·兰迪斯,他们在1962年的论文《An algorithm for the organization of information》中公开了这一数据结构。 AVL树是一种自平衡二叉搜索树,在AVL树中任一节点对应的两棵子树的最大高度差为1,查找、插入和删除在平均和最坏情况下的时间复杂度都是O(log n),增加和删除元素的操作则可能需要借由一次或多次树旋转,以实现树的重新平衡。 平衡因子:节点的平衡因子是它的左子树的高度减去它的右子树的高度(有时相反)。 旋转操作: 右旋 左旋 需要平衡的四种情况: B-树 参考文章 B-树就是B树,中间的横线并不是减号 为什么数据库索引使用B-树而不是二叉搜索树? 考虑磁盘IO的问题,数据库索引是存储在磁盘上的,当数据量比较大的时候,索引的大小可能有几个G甚至更多,当我们利用索引查询的时候只能逐一加载每一个磁盘页这里的磁盘页对应索引树的节点,最坏情况下磁盘IO次数等于索引树的高度,所以需要把原本“瘦高”的树结构变得“矮胖”,这就是B-树的特征之一。 B树是一种多路平衡查找树,每个节点最多可以包含k个孩子,k为B树的阶(k的选择取决于磁盘页大小) 一个m阶的B树具有如下几个特征: 若根节点不是叶子节点则至少有两个子节点每个中间节点都包含 k-1 个元素和 k 个孩子,其中 ⌈m/2⌉ <= k <= m每个叶子节点都包含 k-1个元素,其中⌈m/2⌉ <= k <= m所有的叶子节点都位于同一层每个节点中的元素从小到大排列,节点当中k-1个元素刚好是k个孩子包含的元素的值域分划。 B-树主要应用于文件系统以及部分数据库索引,比如著名的非关系型数据库MongoDB,大部分关系型数据库比如Mysql则使用B+树作为索引。 B树的插入操作 参考博客 插入操作是指插入一条记录,即(key, value)的键值对。如果B树中已存在需要插入的键值对,则用需要插入的value替换旧的value。若B树不存在这个key,则一定是在叶子结点中进行插入操作。 1)根据要插入的key的值,找到叶子结点并插入。 2)判断当前结点key的个数是否小于等于m-1,若满足则结束,否则进行第3步。 3)以结点中间的key为中心分裂成左右两部分,然后将这个中间的key插入到父结点中,这个key的左子树指向分裂后的左半部分,这个key的右子支指向分裂后的右半部分,然后将当前结点指向父结点,继续进行第3步。( 当阶数m为偶数时,需要分裂时就不存在排序恰好在中间的key,那么我们选择中间位置的前一个key或中间位置的后一个key为中心进行分裂即可。 ) 以5阶B树为例,介绍B树的插入操作, 在5阶B树中,结点最多有4个key,最少有2个key。 在空树中插入39 此时根结点就一个key,此时根结点也是叶子结点继续插入22、97、41 根结点此时有4个key继续插入53 插入后超过了最大允许的关键字个数4,所以以key值为41为中心进行分裂,结果如下图所示,分裂后当前结点指针指向父结点,满足B树条件,插入操作结束。(当阶数m为偶数时,需要分裂时就不存在排序恰好在中间的key,那么我们选择中间位置的前一个key或中间位置的后一个key为中心进行分裂即可。) 依次插入13、21、40 同样会造成分裂,结果如下图所示。

leetcode:移除元素

和删除有序数组中的重复项是一样的 不理解了,你可以以0,0,1,target=0为例 fast前面探路,slow要保证当前之前都是好的 fast=target了,fast前进即可 !=target了,赋值,slow前进 class Solution { public int removeElement(int[] nums, int val) { int slow = 0; int fast = 0; while(nums.length==0){ return 0; } while(fast<nums.length){ if(nums[fast]!=val){ nums[slow] = nums[fast]; slow = slow + 1; } fast = fast + 1; } return slow; } }

蓝桥杯算法基础(16):十大排序算法(计数排序)(基数排序)c语言版

计数排序 算法思想: 统计原来数组的数据,讲数据转换成下标存储于一个临时的空间中,然后变量临时空间把对应的下标值放回原数组,当遍历临时空间完成后,原来的数组就排好序了 1 2 2 5 3 5 2 6 1 3 8 [0][1][2][3][4][5][6][7][8][9] 0 2 3 2 0 2 1 0 1 0 从小到大该下标位置的值有多少,就打印多少,遍历完成后,就排好序了 1 1 2 2 2 3 3 5 5 6 8 #define 100 N//偷个懒 int temp[N]; void countSort(int arr[],int length){ for(int i=0;i<length;i+=){ temp[arr[i]]++; } for(int i=0,j=0;iNN;i++){ while(temp[i]--)arr[j++]=i; } } //计数排序是不稳定的排序,而且对于其中有一个非常大的数,会占用大量空间,比如1 2 5 2 999999,就需要temp[999999],因此如果计数排序适用于数值较小的数组 基数排序 举例: 154 423 365 251 78 92 640 -------------------------------------- (第一轮)(10的0次方 位即个位)640 251 92 423 154 365 78 (第二轮)(10的1次方 位即十位)423 640 251 154 365 78 92 (第三轮)(10的2次方 位即百位)78 92 154 251 365 423 640 //基数排序需要用到桶 [][][][][][][][][][] [][][][][][][][][][] [][][][][][][][][][] [][][][][][][][][][] [][][][][][][][][][] [][][][][][][][][][] [][][][][][][][][][] 0 1 2 3 4 5 6 7 8 9 int temp[10][N]; //先从个位开始选择放入桶中,随后从十位,百位.

mysql 表的约束

mysql 表的约束 1. 空属性2. 默认值3. 列描述4. zerofill5. 主键6. 自增长7. 唯一键8. 外键 1. 空属性 在数据库中,每个字段都有一个空属性,可以是 NULL(默认)或 NOT NULL(不为空)。一般来说,应尽可能保证字段不为空,因为空值在实际运算中可能会导致问题。 示例:创建一个班级表,其中班级名称不能为空,而教室名称也不能为空。 CREATE TABLE myclass ( class_name VARCHAR(20) NOT NULL, classroom VARCHAR(10) NOT NULL ); 插入示例: INSERT INTO myclass (class_name, classroom) VALUES ('班级A', '教室101'); 错误的插入示例: -- 会导致错误,因为 class_name 不能为空 INSERT INTO myclass (classroom) VALUES ('教室101'); -- 会导致错误,因为 classroom 不能为空 INSERT INTO myclass (class_name) VALUES ('班级A'); 2. 默认值 某些字段的数据经常会出现相同的默认值,可以在表的设计阶段指定默认值,从而在需要时使用该值。 示例:创建一个学生表,其中年龄默认为 0,性别默认为男性。 CREATE TABLE students ( name VARCHAR(50) NOT NULL, age TINYINT UNSIGNED DEFAULT 0, sex CHAR(2) DEFAULT '男' ); 插入示例:

Hadoop大数据应用:Yarn 节点实现扩容与缩容

目录 一、实验 1.环境 2.Yarn 节点扩容 3.Yarn 节点缩容 二、问题 1.yarn启动服务报错 一、实验 1.环境 (1)主机 表1 主机 主机架构软件版本IP备注hadoop NameNode (已部署) SecondaryNameNode (已部署) ResourceManager(已部署) hadoop 2.7.7192.168.204.50 node01 DataNode(已部署) NodeManager(已部署) hadoop 2.7.7192.168.204.51node02 DataNode(已部署) NodeManager(已部署) hadoop 2.7.7192.168.204.52node03 DataNode(已部署) NodeManager(已部署) hadoop 2.7.7192.168.204.53node05NodeManager hadoop 2.7.7192.168.204.55 (2)查看jps hadoop节点 [root@hadoop hadoop]# jps node01节点 node02节点 node03节点 (3) 查看节点 [root@hadoop hadoop]# ./bin/yarn node -list 24/03/14 13:40:21 INFO client.RMProxy: Connecting to ResourceManager at hadoop/192.168.204.50:8032 Total Nodes:3 Node-Id Node-State Node-Http-Address Number-of-Running-Containers node01:40551 RUNNING node01:8042 0 node02:46073 RUNNING node02:8042 0 node03:40601 RUNNING node03:8042 0 2.

java垃圾回收-三色标记法

三色标记法 引言什么是三色标记法白色灰色黑色 三色标记过程三色标记带来的问题多标问题漏标问题 如何弥补漏标问题增量更新原始快照总结 引言 在CMS,G1这种并发的垃圾收集器收集对象时,假如一个对象A被GC线程标记为不可达对象,但是用户线程又把A对象做清楚时 将会发生严重的错误,那么jvm是如何处理这种问题呢? 什么是三色标记法 主流的垃圾收集器基本上都是基于可达性分析算法来判断对象是否存活的,根据对象是否被垃圾收集器扫描过而用黑白灰三种颜色来标记对象状态的方法。 白色 表示对象尚未被垃圾收集器扫描过。在可达性分析开始阶段,所有的对象都是白色的。若在分析结束后对象仍是白色,则代表对象为不可达对象,需要对这些对象进行回收。 灰色 表示对象已经被垃圾回收器访问过,但这个对象至少存在一个引用还没被扫描过。 黑色 表示对象已经被垃圾收集器访问过,且这个对象的所有引用都已经扫描过。 黑色的对象代表已经被扫描过,他是安全存活的,如果有其他对象引用指向了黑色对象,无需重新扫描一遍。黑色对象不可能直接指向某个白色对象。 三色标记过程 在gc线程开始标记的时候,所有的对象都是白色,全部放入白色节点集合中。 然后从gc root set开始进行扫描,首先node1,node5 被扫描到,node 1、5被标记成灰色节点,从白色节点集合中挪到灰色节点集合中。 注意,这里只遍历一次root set集合,不是递归遍历。 3, 然后gc会从灰色节点开始继续向下扫描,也就是从node1,node5(被标记成灰色的节点)开始,然后扫描到node2,node6 会被标记成灰色,然后node2,node6从白色集合挪到灰色集合。然后node1,node5因为已经被扫描过了会被标记成黑色,然后从灰色几点挪到黑色节点结合中。 继续从灰色节点node2,node6开始往下遍历,因为node2,node6已经被扫描过了,所以会被标记成黑色节点,从灰色节点挪到黑色节点集合中。 node3节点被标记成灰色节点,从白色节点挪到灰色节点集合中。 继续从灰色节点node3开始遍历,直到最终没有了灰色节点就不会再往下遍历了,因为Node3被遍历过了,所以会被标记为黑色,从灰色集合中挪到黑色集合中。最终只会剩下两种状态的节点(只有黑色和白色)。 最终回收完垃圾节点就只只剩下标记成黑色状态的节点,这就是整个过程。 三色标记带来的问题 因为cms和g1垃圾回收器是一个并发回收的回收器,标记线程和用户线程是并发执行的,那么就有可能在标记过程中,用户线程修改了对象的引用关系,造成多标,或者漏标。那么针对这些问题jvm又是怎么处理的呢? 多标问题 假如gc线程已经扫描到了对象e,此时e为灰色,说巧不巧这个时候用户现成ObjectC.e=null, 将c的引用e断开了。因为e是灰色,gc就会认为e对象是可达对象,而不会对e进行回收,但实际上e是个浮动垃圾,但实际上还可以接受,因为等到下次垃圾回收的时候可以回收掉。但并不代表就不是缺点,如果浮动垃圾较多,可能触发full gc。 漏标问题 假如用户线程断开了c到e的引用,那么e对象就是不可达对象,而此时b对象又引用了e对象,但是三色标记又不会重新从b点开始标记到e,那么e就会被认为是垃圾对象,但实际e是有引用的。如果对e进行垃圾回收,就会产生错误,这就就漏标问题。 如何弥补漏标问题 我们仔细观察漏标,会发现,这种场景的出现是有条件的, 黑色对象被插入了一条或者多条白色引用。灰色对象删除了白色对象的引用。 可以归结为: 赋值器插入了一条或者多条从黑色对象到白色对象的引用。赋值器删除了所有的从灰色对象到白色对象的直接引用或者间接引用。 因此,只要侦查到这2个条件的发生即可,所以产生了两种解决方案——增量更新(Incremental Update)和原始快照(Snapshot At The Beginning, SATB)。 增量更新 增量更新破坏的是第一个条件,当黑色对象插入新的指向白色对象的引用关系时。就将这个新插入的引用记录下来,等并发扫描结束之后,再将这些记录过的引用关系中的黑色对象作为根对象,再重新扫描一遍。比如漏标问题中,一旦B对象直接指向了E对象,那么在并发扫描之后,就会将B对象作为灰色对象,再重新扫描一遍。这样虽然避免了漏标问题,但是重新标记会导致STW的时间变长。 原始快照 原始快照破坏的是第二个条件,当灰色对象要删除指向白色对象的引用关系时,就将这个要删除的引用记录下来,在并发扫描结束之后再将这些记录过的引用关系中的灰色对象为根对象再重新扫描一遍。例如漏标问题的途中,C断开E的引用关系时会保存一个快照,然后等扫描结束之后,会把C当作根再重新扫描一遍,假如B没有引用E,那么E对象也会认为是可达对象,这样E就成了浮动垃圾,只能等下次垃圾回收时再回收。 总结 无论是对引用关系记录的插入还是删除,虚拟机的记录操作都是通过写屏障实现的。在HotSpot虚拟机中,CMS是基于增量更新来做并发标记的,G1、Shenandoah则是用SATB来实现的。

Helm Chart部署最简SpringBoot到K8S(AWS EKS版)

目标 这里假设,我们已经基本会使用k8s的kubectl命令进行部署了,也已经会自己打docker镜像推送到AWS ECR上面去了。而且,已经在云上准备好了AWS ECR镜像库和AWS EKS的k8s集群了。 这个前提上面,我们今天使用Helm Chart项目准备k8s的yaml配置文件来部署一个最简单的Springboot项目到AWS的k8s集群。 Helm项目结构 . └── my-kubernetes-app ├── configmaps ├── crons ├── deployments ├── hpas ├── pdbs ├── podpriorities ├── pvcs ├── services ├── statefulsets └── ... 上面这个是网上一位工友总结出来的Helm Chart目录结构。在这之前,还是先了解了解Helm是干什么的吧?Helm自身定位是给k8s的包管理器,但是,他的Helm Chart项目被我们现在这里用于管理生成k8s配置模板,来生成不同环境的k8s yaml配置文件。简单来说,Helm Chart就是一个根据模板生成配置文件的工具。 下面是我这次用的Helm目录结构: ./ ├── Chart.yaml ├── templates │ ├── configmaps │ │ ├── demo.yaml │ │ └── demo2.yaml │ ├── ingress.yaml │ ├── secrets │ │ └── mysql.yaml │ └── services │ ├── demo.yaml │ └── demo2.