2023年4月


一、VsCode 常见的配置

1、取消更新

  • 把插件的更新也一起取消了


2、设置编码为utf-8:默认就是了,不用设置了


3、设置常用的开发字体:Consolas, 默认就是了,不用设置了

  • 字体对开发也很重要,不同字体,字母形态都不太一样,尤其是标点符号,逗号和分号的区分,有的字体看着这两者就很像


4、设置ctr+滚轮,改变字体大小


5、设置行号:默认就有,不用设置了


6、自动保存:


7、设置选项卡多行展示

  • 这样打开了很多个文件,就不会导致有的打开的文件被隐藏


8、设置查看当前类或文件的结构 OUTLINE

  • 相当于idea 查看当前类或接口的结构 Structure



二、VsCode 常用好用插件

1、实时刷新网页的插件:LiveServer


2、open in browser

支持快捷键与鼠标右键快速在浏览器中打开html文件,支持自定义打开指定的浏览器,包括:Firefox,Chrome,Opera,IE以及Safari


补充一下:LiveServer 和 open in browser 区别:注意观察浏览器地址栏

  • open in browser:直接打开HTML文件就是通过File协议打开的
  • LiveServer: 通过http 协议打开的,地址栏会上看到主机名, Live Server启动了一个本地开发服务器,静态和动态页面都可以实时重载。

3、自动闭合HTML/XML标签:Auto Close Tag


4、图片自动检查:Image preview


5、资源树目录:vscode-icon

它不仅能够给文件夹、文件添加上舒适的图标,而且可以自动检测项目,根据项目不同功能配上不同图标


6、AI 智能提示的插件:Tabnine

用IDE编写代码的时候可以给出智能提示,写的越多提示的越准确




选择性安装的插件

像颜色提示、主题那种,还有语法检查、语法智能提示等

本地历史代码记录: local history

git相关的插件:Git History

  • Git History提供了一个可视化的git日志。不再需要在终端查看git日志。可以比较各个分支、提交和跨提交的文件。

HTML CSS Support

  • 智能提示CSS类名以及id

HTML Snippets

  • 智能提示HTML标签,以及标签含义

JavaScript(ES6) code snippets

  • ES6语法智能提示,以及快速输入,不仅仅支持.js,还支持.ts,.jsx,.tsx,.html,.vue,省去了配置其支持各种包含js代码文件的时间

jQuery Code Snippets

  • jQuery代码智能提示

CSS Peek

  • 使用此插件,你可以追踪至样式表中 CSS 类和 ids 定义的地方。当你在 HTML 文件中右键单击选择器时,选择“ Go to Definition 和 Peek definition ”选项,它便会给你发送样式设置的 CSS 代码。



一、VsCode 开发相应项目推荐安装的插件

1、开发 Vue 项目必装的插件

(1)【vue2】安装一个方便阅读 vue 代码的插件:Vetur

  • 安装之后,vue 代码,文本颜色开始发生变化[注释是绿色的哈哈哈],不安装,代码全是白色的。

Vetur插件介绍:功能包括-
语法高亮
,智能提示,emmet,错误提示,格式化,自动补全,debugger。vscode官方钦定Vue插件,Vue开发者必备。

  • vue3 使用的是插件 Vue Language Features (Volar)


2、开发 Lua 项目必装的插件

(1) 安装一个方便阅读 lua 代码的插件:lua




如果本文对你有帮助的话记得给一乐点个赞哦,感谢!




全文快读

  • 题目:Multi-fidelity Reinforcement Learning With Gaussian Processes: Model-Based and Model-Free Algorithms
  • 链接:
    https://ieeexplore.ieee.org/abstract/document/9069479
  • IEEE Robotics & Automation Magazine 是 robotics 顶刊。
  • main idea:
    • 基于 14 年的最初的那篇
      MFRL 论文

      本站博客
      ),
    • 利用相邻 state-action 的空间相关性来加速学习,用 gaussian processes 建模 env dynamics(model-based)/ Q function(model-free),从而得到 model-based model-free 两种 MFRL 算法。
    • 算法结构跟 14 年的 MFRL 基本一致。
  • 全文没有数学证明。

1 intro

  • 利用相邻 state-action 的空间相关性来加速学习:通过 Gaussian Process(GP)作为函数逼近器。
  • 主要贡献:两个算法。
    • model-based MFRL 算法 GP-VI-MFRL,估计转换函数,然后使用 value iteration 计算最优策略。
    • model-free MFRL 算法 GPQ-MFRL,直接估计最优 Q 值以及随后的最优策略。

3 背景

4 method

4.1 model-based 算法:GP-VI-MFRL

image-20230416114107971

  • 结构:包括 1 model learner、2 planner。
    • model learner 使用 GP regression 学 env transition: s_{t+1} = f(s_t,a_t),使用高斯分布的形式。
    • 使用 value iteration 作为 planner,用学到的 env transition 计算出最优策略。
  • 算法:
    • 在执行一个 action 前,agent 检查(第 8 行)它是否对当前 state-action pair 在前一个模拟器 Σi-1 中的 transition function 有足够准确的估计(方差小于 σ_th)。
      • 如果不是,并且如果当前环境中的 transition model 发生了变化,它就会切换到 Σi-1,并在 Σi-1 中执行 action 。
    • 跟踪当前模拟器中,最近访问的 L 个 state-action 对的方差。若方差和低于阈值 σ_th^sum(第 15 行),表明 agent 对当前模拟器很有信心,可以推进到下一个模拟器。
      • 在最初的工作中 [2],agent 遇到一定数量的已知 state-action 对后,就会切换到更高保真度的模拟器。
    • (第 7 行)如果一个 state-action pair 的后验方差下降到阈值 σ_th 以下(即 agent 对该 transition 有足够准确的估计),当前环境的模型就会改变,即 change = TRUE。
    • 第 10 - 13 行描述了算法的主体, agent 执行贪婪地选择的 action(第 6 行),并在 Di 中记录观察到的 transition (第 11 行)。 transition function 的 GP 模型在每一步之后被更新(第 12 行)。每次更新 transition function 后,都会计算新的 Q 值估计(第 13 行)。
      • 对每个模拟器,使用一个单独的 GP 来估计它的 transition function 。
    • 终止条件(第 5 行):步数限制、价值函数的变化、最大的 env 切换次数…
    • planner 利用上级(第 26 - 28 行)和下级模拟器(第 25 行)的转换知识,鼓励当前模拟器的探索。
      • 对于每一个 state-action pair (s,a),planner 寻找最大保真度的模拟器(第 26 行遍历所有模拟器),这个模拟器对 (s,a) 的 transition 有一个已知的估计(第 28 行),使用这个估计在当前模拟器中进行规划(第 28 行)。
        • 如果方差低于一个阈值,那么一个估计值就被称为“已知”。
      • 如果没有这样的模拟器,那么它就使用在前一个模拟器中学到的 Q 值,再加上一个保真度参数 β(第 25 行),这个参数是连续的模拟器中最佳 Q 值之间的最大可能差异。
    • 必须进行状态空间离散化,以规划 action 。然而,学到的 transition function 是连续的。

4.2 model-free 算法:GPQ-MFRL

image-20230416114222956

  • 直接使用 GPs 学习最佳 Q 值,而非学习 env model。
    • 基本假设:附近的 state-action pair 产生类似的 Q 值。
    • GPs 使用 squared-exponential kernel。
    • 同样,每个模拟器使用单独的 GP。
  • 算法:
    • 使用类似的阈值(σ_th 和 σ_th^sum)来确定何时切换到低保真或高保真模拟器。
    • GPQ-MFRL 检查 agent 在前一个模拟器中是否对最佳 Q 值有足够准确的估计(第 8 行),如果没有,切换到前一个模拟器。
    • 第 10 - 15 行描述了算法的主体,agent 将 transition 存入 Di(第 11 行),然后为每个 Di 中的 transition 更新目标值(第 14 行)(batch training)。GP 模型在每一步后被更新(第 16 行)。
    • agent 利用在上级模拟器中收集的经验(第 25 - 27 行)来选择当前模拟器中的最佳行动(第 6 行),利用最高已知 Q 值((s,a) 的后验方差小于阈值 σ_th)的模拟器(第 27 行),来选择当前模拟器的下一个动作。
      • 如果不存在这样的高保真模拟器,则使用低一层模拟器的 Q 值(第 24 行),使用保真度参数 β。
    • 每当 agent 在模拟器中收集到新的样本时,GPQ-MFRL 就会进行一次 batch re-training(第 13 - 15 行),使用新样本的知识,更新以前训练数据的 y 值。
    • 然后,用这些更新的 y 值,来训练 GPs 形式的 Q 值(第 16 行)。
      • 更新 GP 的计算成本是数据量的三次方;然而,我们可以使用稀疏 GP 技术 [6] 对数据集进行修剪,即,只用一小部分数据来 fit GP。
    • 不容易选择置信度界限的值。在目前的实验中,我们选择 σ_th^sum 为可能的最大 Q 值的 10%,σ_th 为 σ_th^sum 的 1/5。

5 experiment

  • 写的蛮清楚的。
  • GP-MFRL 比 14 年最初的 MFRL 效果更好(用的 high-fidelity 样本更少)。
  • GP-VI-MFRL(model-based)在训练最开始时比 GPQ-MFRL(model-free)表现更好,与传统 RL 经验一致,即 model-based>model-free。

6 讨论与展望

  • 未来可以将 MFRL 技术与 sim2real 方法进行比较 [1]。
    • 与 sim2real 不同的是,MFRL 技术明确决定何时在模拟器之间切换,并使用两层以上的模拟器。
    • 或许可以将这两个想法结合起来:使用 MFRL 来利用一些更便宜 / 更快的模拟器;使用参数化的模拟器,来引入领域适应 / 随机化(domain adaptation/randomization),以获得更好的 generalization。
  • 可改进的地方:在目前的方法中,进行 GP 回归时,来自不同模拟器的数据没有结合起来。
    • 1 使用多任务 GPs,它可以同时产生多个输出,分别对应于每个保真度模拟器。
    • 2 使用 deep GP ,将不同保真度的数据 拿来训同一个 NN。
    • 对以上两种情况,我们希望直接学习不同环境下的数值之间的相关性。



转载请注明出处:

1.nginx如何自定义负载均衡

在Nginx中,可以通过配置文件自定义负载均衡策略。具体步骤如下:

  1. 首先,在Nginx配置文件中定义一个upstream模块,并设置负载均衡策略和后端服务器列表,例如:

upstream myapp {
server backend1.example.com weight
=3;
server backend2.example.com;
server backend3.example.com;
hash $remote_addr consistent;
}

其中,myapp是一个自定义的upstream名称,backend1.example.com、backend2.example.com、backend3.example.com是后端服务器的地址或域名。weight=3表示给backend1.example.com设置权重为3,而backend2.example.com和backend3.example.com的权重默认为1。hash $remote_addr consistent表示采用基于客户端IP地址的一致性哈希算法进行负载均衡。

2. 然后,在server模块中配置具体的代理规则,将请求代理到upstream中定义的服务器列表中,例如:

server {
listen
80;
server_name example.com;
location
/{
proxy_pass http:
//myapp;
}
}

其中,proxy_pass
http://myapp 表示将请求代理到myapp定义的服务器列表中进行负载均衡。

3. 最后,重新加载Nginx配置文件,使其生效:

sudo nginx -s reload

需要注意的是,Nginx支持多种负载均衡策略,例如轮询(默认)、IP哈希、URL哈希、加权轮询等。可以根据实际情况选择不同的负载均衡策略,并根据需要调整后端服务器列表的权重等参数,以实现自定义的负载均衡策略。

2.如何自定义根据cpu的运行情况进行负载均衡配置

可以使用Nginx的ngx_http_upstream_module模块和Lua脚本语言实现根据CPU的运行情况进行负载均衡配置。具体步骤如下:

  1. 安装ngx_http_lua_module模块,该模块提供了在Nginx中运行Lua脚本的能力。

  2. 在Nginx配置文件中定义upstream模块,并设置负载均衡策略和后端服务器列表,例如:

upstream myapp {
server backend1.example.com;
server backend2.example.com;
}

3.在server模块中定义Lua脚本,并在其中编写根据CPU运行情况进行负载均衡的代码,例如:

server {
listen
80;
server_name example.com;
location
/{
access_by_lua_block {
local status = require "ngx.status"
local cpu =status.get_cpu()local servers =ngx.shared.serverslocal peer =servers:get(cpu)if not peer then
local peers = {"backend1.example.com", "backend2.example.com"}local index = cpu % #peers + 1peer=peers[index]
servers:set(cpu, peer,
60 * 5) --缓存5分钟
endngx.var.backend=peer
}
proxy_pass http:
//$backend;
}
}

4. 在Nginx配置文件中添加shared_dict指令,用于共享服务器列表和CPU状态信息:

http {
lua_shared_dict servers 1m;
lua_shared_dict status 1m;
...
}

5.最后,重新加载Nginx配置文件,使其生效:

sudo nginx -s reload

该方法仅仅是一个参考,真实场景下,CPU的负载情况并不是唯一的考虑因素,还需要考虑网络延迟、后端服务器的性能、负载均衡的稳定性等因素。

原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,非公众号转载保留此声明。

在之前的OOM问题复盘中,我们添加了jmap脚本来自动dump内存现场,方便排查OOM问题。

但当我反复模拟OOM场景测试时,发现jmap有时可以dump成功,有时会报错,如下:
jmap_failed
经过网上一顿搜索,发现两种原因可能导致这个问题,一是执行jmap用户与jvm进程用户不一致,二是
/tmp/.java_pidXXX
文件被删除,但经过检查,这都不是我们jmap失败的原因。

经过了解,jmap导出内存的原理,大致如下:
jmap

  1. 如果jvm进程id是8255,jmap会先创建一个
    /tmp/.java_pid8255
    文件,然后发送SIGQUIT信号给jvm。
  2. jvm收到信号后启动AttachListener线程,以UNIX domain socket的形式监听
    /tmp/.java_pid8255
    文件,以接收命令。
  3. jmap也以UNIX domain socket的形式连接上
    /tmp/.java_pid8255
    文件,并发送dumpheap命令给jvm,这个过程中jvm会检查命令发送方用户的euid/egid是否与自己一致。
  4. AttachListener线程收到dumpheap命令后,等到JVM进入Safepoint后,执行HeapDumper操作以导出heap.hprof文件。

可以看出,当jvm已经卡死,或有长时间的GC正在Safepoint中执行,都会导致jmap长时间读不到命令的响应而超时失败!

使用jmap -F

当给jmap添加
-F
参数时,jmap会使用Linux的
ptrace
机制来导出堆内存,
ptrace
是Linux平台的一种调试机制,像strace、gdb都是基于它开发的,它使得调试进程(jmap)可以直接读取被调试进程(jvm)的原生内存,然后jmap再根据jvm的内存布局规范,将原生内存转换为hprof格式。

但在实际执行时,会发现
jmap -F
执行得非常慢,可能要几个小时,这是因为
ptrace
每次只能读一个字的内存,而我们的堆有10G,因此
jmap -F
对于我们几乎无法使用。

注:这里说的原生程序,指的是类似于C/C++这种直接编译出来、不需要依赖语言虚拟机的程序,而原生内存,指的是通过malloc或mmap等直接申请出来的内存。

使用gcore

有过Linux下原生程序调试经验的,应该会知道gcore这个实用工具,它可用来生成程序原生内存的core文件,然后jstack、jmap等都可以读取此类文件,如下:

# 生成core文件,8787是进程号
$ gcore -o core 8787
Saved corefile core.8787
[Inferior 1 (process 8787) detached]

$ ll -lh core.8787
-rw-r--r-- 1 work work 5.8G 2023-04-16 11:40:00 core.8787

# 从core文件中读取线程栈
$ jstack `which java` core.8787

# 将core文件转换为hprof文件,很慢,建议摘流量后执行
$ jmap -dump:format=b,file=heap.hprof `which java` core.8787

但是当我使用jmap转换core文件时,我发现我本机测试时可以成功,但在测试服务器上却一直报错,如下:
core_to_hprof_fail
我网上找了好久,都没找到报此错误的原因...

但我发现gcore执行时,是有一些警告信息的,如下:
gcore_warn
看起来可能是gcore导出的core文件不全,联想到jvm部署在容器中,怀疑是有某些权限限制,导致部分程序内存导出失败了。

使用Linux内核的coredump机制

除了gcore可以导原生内存,其实Linux内核也有自动的coredump机制,即进程在收到某些信号后,会自动触发内核的coredump机制,内核会负责将进程的原生内存保存为core文件,而内核一般是最高权限运行的,所以它生成的core文件应该是完整的。

先开启coredump机制,如下:

# 检查是否开启,输出unlimited表示core文件不受限制,即完全开启
$ ulimit -c

# 临时开启coredump
$ ulimit -c unlimited

# 永久开启
$ echo "ulimit -c unlimited" >> /etc/profile

然后,配置一下coredump文件保存位置,如下:

# 查看当前配置
$ cat /proc/sys/kernel/core_pattern
/home/core/core.%e.%p.%t

# 配置coredump文件保存位置,并使其生效
$ vi /etc/sysctl.conf
kernel.core_pattern=/home/core/core.%e.%p.%t
$ sysctl –p /etc/sysctl.conf

core_pattern占位符解释

占位符 解释
%p pid
%u uid
%g gid
%s signal number
%t UNIX time of dump
%h hostname
%e executable filename

注:如果没有权限修改core_pattern路径,可考虑使用软链接
ln -s
做路径跳转,当然,还需要保证coredump路径有写入权限。

配置ok后,可通过kill发送信号来触发内核coredump,可触发coredump的常见信号如下:

  • SIGQUIT 数值2 从键盘输入
    Ctrl+'\'
    可以产生此信号
  • SIGILL 数值4 非法指令
  • SIGABRT 数值6 abort调用
  • SIGSEGV 数值11 非法内存访问
  • SIGTRAP 数值5 调试程序时使用的断点

我选择了SIGABRT信号,即
kill -6
,经过验证,可生成core文件,而且core文件也能被jmap转换为hprof文件。


有了hprof文件,就可以愉快地使用MAT、JVisualVM、JMC等工具进行内存分析啦

宏基因组篇

前言

之前的一篇
文章
已经从生物实验的角度讲述了高通量测序的原理,这篇文章旨在介绍宏基因组二代测序数据的处理方式及其原理。在正文开始之前,我们先来认识一下什么是宏基因组。以我的理解,宏基因组就是某环境中所有生物的基因组的合集,这个环境可以是下水道,河流等自然环境,也可以是人体内肠道,口腔等体环境。而宏基因组中的生物往往指的是微生物,如真菌,细菌,病毒,古细菌。

我们这里主要以肠道微生物为例,也就是人体内肠道的宏基因组。肠道菌群的测序样本往往是粪便样本,现在主流的测序方式有两种:一种是16sRNA测序,一种是WGS(Whole Genome Sequencing) 全基因组测序。WGS测序数据量更大,所包含的信息更多,能注释出物种-样本的丰度矩阵,也能注释出基因-样本的丰度矩阵。而16sRNA测序测的是细菌核糖体RNA中的小亚基,这个小亚基的沉降系数是 16s,故被称为 16s RNA,这个16s RNA有一段非常保守的序列和一段变异序列,可以根据16s RNA 的变异度来进行物种分类,所以16s RNA数据往往只能注释出物种-样本的丰度矩阵。

原理介绍

之前
文章
中也提到了,由于测序技术的限制,目前二代测序只能测较短的碱基片段,所以需要对基因进行碎片化,我们要思考的问题就是这些碎片化的基因如何重新拼回到完整的基因组或者这些碎片化的基因如何确定其属于什么物种从而得到物种的丰度矩阵。

目前对宏基因组原始数据如何注释到物种的方法有两类主流方法,一类是基于bin进行物种注释的方法,一类是不基于bin进行物种注释的方法

基于bin的物种注释

基于bin的物种注释的代表软件有 metawrap,metabat2等。

在宏基因组的原始数据也就是fastq数据中,含有大量的read序列,首先是将read按照序列拼接成contigs,如图所示,上面的的read按照序列重合程度拼接成下面的contigs。

read拼接成contigs

然后把相类似的contigs归为一个bin,而具体如何归bin的方法各种软件所用的原理都有些区别,这里介绍两种方法,也是
这个视频
中提到的两种分类的方法,第一种是依据四碱基频率来进行区分,所谓四碱基频率就是ATGC四个碱基为一组,共256种碱基组合,同一种物种的这256碱基组合的频率是相似的,并且物种亲缘关系越远则四碱基频率差距越大,故这一个256维的向量可以进行PCA降维,然后用聚类方法将类似的contigs聚到一起作为一个bin。

256维的四碱基频率PCA图

第二种方法是基于测序深度的,他的基本原理是由于不同的物种基因组大小不同,而同一种物种的基因组大小是类似的,因此可以根据contigs的深度来判断其是否为同一个物种,物种的基因组越大,在随机打碎DNA时产生的碎片越多,read数越高,最后通过read拼接而成的contigs的深度越大。

总而言之,bin就是一堆亲缘关系较近的contigs的合集,也可以视为一个物种基因组的草图。

得到高质量bin后就是对他进行基于数据库的注释,将能注释出来的bin注释出来。而bin的丰度,也就是物种的丰度的计算方式就是bin上每个碱基的深度除以bin序列长度。
这个计算方式不太确定,推测的,暂时没找到资料

不基于bin的物种注释

基因bin的物种注释更加准确,但是耗时更长,这里再介绍一类直接从read比对数据得到物种丰度的宏基因组数据处理的方式,代表的软件有 kraken,metaphlan等。

kraken注释原理

这里主要以kraken的原理为例,它实际上就是将read 分成了多个 k-mers。 这个k-mers的意思就是是k bp长度的子序列,只不过这个子序列覆盖了read所有碱基,如150bp的read 能拆分出
150-31+1

31-mer
, k-mers中的k长度是自定义的,默认是31,然后将这些 k-mers去跟数据库比对,k-mers对上最多的分支就作为这个read的物种分类,如上图,这个序列就是被认为是来自与4号物种的序列。同样的,将每个物种比对上的read数量除以其基因组长度就得到了其丰度。

参考链接

[1] 宏基因组分箱原理

[2] 从CONCOCT入手理解宏基因组binning

[3] kraken注释原理