本笔记由学习MLIR Tutorials总结而成,欢迎批评指正。

Chapter1: Toy语言和AST

MLIR提供了一种Toy语言来说明MLIR的定义和执行的流程。Toy语言是一种基于张量的语言,我们可以使用它来定义函数,执行一些数学计算以及输出结果。下面要介绍的例子中限制Tensor的维度是<=2的,并且Toy语言中唯一的数据类型是64位浮点类型,对应C语言中的"double"。另外Values是不可以重写的,即每个操作都会返回一个新分配的值,并自动管理释放。直接看下面这个例子:

def main() {# Define a variable `a` with shape <2, 3>, initialized with the literal value.# The shape is inferred from the supplied literal.var a = [[1, 2, 3], [4, 5, 6]];# b is identical to a, the literal tensor is implicitly reshaped: defining new# variables is the way to reshape tensors (element count must match).var b<2, 3> = [1, 2, 3, 4, 5, 6];# transpose() and print() are the only builtin, the following will transpose# a and b and perform an element-wise multiplication before printing the result.print(transpose(a) * transpose(b));
}

类型检查是通过类型推断静态执行的。Toy语言只需在必要时指定Tensor形状的类型声明。下面定义了一个multiply_transpose函数,注意这个函数里面参数ab的形状我们预先都是不知道的,只有调用这个函数时我们才知道,可以关注一下下面例子中的shape变化。

# User defined generic function that operates on unknown shaped arguments.
def multiply_transpose(a, b) {return transpose(a) * transpose(b);
}def main() {# Define a variable `a` with shape <2, 3>, initialized with the literal value.var a = [[1, 2, 3], [4, 5, 6]];var b<2, 3> = [1, 2, 3, 4, 5, 6];# This call will specialize `multiply_transpose` with <2, 3> for both# arguments and deduce a return type of <3, 2> in initialization of `c`.var c = multiply_transpose(a, b);# A second call to `multiply_transpose` with <2, 3> for both arguments will# reuse the previously specialized and inferred version and return <3, 2>.var d = multiply_transpose(b, a);# A new call with <3, 2> (instead of <2, 3>) for both dimensions will# trigger another specialization of `multiply_transpose`.var e = multiply_transpose(b, c);# Finally, calling into `multiply_transpose` with incompatible shape will# trigger a shape inference error.var f = multiply_transpose(transpose(a), c);
}

然后我们可以使用下面的命令来产生这个Toy语言程序的AST:

cd llvm-project/build/bin
./toyc-ch1 ../../mlir/test/Examples/Toy/Ch1/ast.toy --emit=ast

前提是要构建好llvm-project工程,构建过程按照https://mlir.llvm.org/getting_started/ 这里的方法操作即可,这里再列一下完整过程:

$ git clone https://github.com/llvm/llvm-project.git
$ mkdir llvm-project/build
$ cd llvm-project/build
$ cmake -G "Unix Makefiles" ../llvm \-DLLVM_ENABLE_PROJECTS=mlir \-DLLVM_BUILD_EXAMPLES=ON \-DLLVM_TARGETS_TO_BUILD="host" \-DCMAKE_BUILD_TYPE=Release \-DLLVM_ENABLE_ASSERTIONS=ON 
$ cmake --build . --target check-mlir

上面Toy程序产生的AST长下面这样:

Module:Function Proto 'multiply_transpose' @../../mlir/test/Examples/Toy/Ch1/ast.toy:4:1Params: [a, b]Block {ReturnBinOp: * @../../mlir/test/Examples/Toy/Ch1/ast.toy:5:25Call 'transpose' [ @../../mlir/test/Examples/Toy/Ch1/ast.toy:5:10var: a @../../mlir/test/Examples/Toy/Ch1/ast.toy:5:20]Call 'transpose' [ @../../mlir/test/Examples/Toy/Ch1/ast.toy:5:25var: b @../../mlir/test/Examples/Toy/Ch1/ast.toy:5:35]} // BlockFunction Proto 'main' @../../mlir/test/Examples/Toy/Ch1/ast.toy:8:1Params: []Block {VarDecl a<> @../../mlir/test/Examples/Toy/Ch1/ast.toy:11:3Literal: <2, 3>[ <3>[ 1.000000e+00, 2.000000e+00, 3.000000e+00], <3>[ 4.000000e+00, 5.000000e+00, 6.000000e+00]] @../../mlir/test/Examples/Toy/Ch1/ast.toy:11:11VarDecl b<2, 3> @../../mlir/test/Examples/Toy/Ch1/ast.toy:15:3Literal: <6>[ 1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00] @../../mlir/test/Examples/Toy/Ch1/ast.toy:15:17VarDecl c<> @../../mlir/test/Examples/Toy/Ch1/ast.toy:19:3Call 'multiply_transpose' [ @../../mlir/test/Examples/Toy/Ch1/ast.toy:19:11var: a @../../mlir/test/Examples/Toy/Ch1/ast.toy:19:30var: b @../../mlir/test/Examples/Toy/Ch1/ast.toy:19:33]VarDecl d<> @../../mlir/test/Examples/Toy/Ch1/ast.toy:22:3Call 'multiply_transpose' [ @../../mlir/test/Examples/Toy/Ch1/ast.toy:22:11var: b @../../mlir/test/Examples/Toy/Ch1/ast.toy:22:30var: a @../../mlir/test/Examples/Toy/Ch1/ast.toy:22:33]VarDecl e<> @../../mlir/test/Examples/Toy/Ch1/ast.toy:25:3Call 'multiply_transpose' [ @../../mlir/test/Examples/Toy/Ch1/ast.toy:25:11var: b @../../mlir/test/Examples/Toy/Ch1/ast.toy:25:30var: c @../../mlir/test/Examples/Toy/Ch1/ast.toy:25:33]VarDecl f<> @../../mlir/test/Examples/Toy/Ch1/ast.toy:28:3Call 'multiply_transpose' [ @../../mlir/test/Examples/Toy/Ch1/ast.toy:28:11Call 'transpose' [ @../../mlir/test/Examples/Toy/Ch1/ast.toy:28:30var: a @../../mlir/test/Examples/Toy/Ch1/ast.toy:28:40]var: c @../../mlir/test/Examples/Toy/Ch1/ast.toy:28:44]} // Block

AST的解析具体实现在mlir/examples/toy/Ch1/include/toy/Parser.hmlir/examples/toy/Ch1/include/toy/Lexer.h中,感兴趣的读者可以看一下。我对这一块并不熟悉,就暂时不深入下去了,但这个AST看起来还是比较直观的,首先有两个Function对应了Toy程序里面的multiply_transposemain,Params表示函数的输入参数,Proto表示这个函数在ast.toy文件中的行数和列数,BinOp表示transpose(a) * transpose(b)中的*是二元Op,并列出了左值和右值。其它的以此类推也比较好理解。

第一章就是简单介绍了一下Toy语言的几个特点以及Toy示例程序产生的AST长什么样子,如果对AST的解析感兴趣可以去查看代码实现。

Chapter2. 生成初级MLIR

MLIR 被设计成完全可扩展的基础框架,没有封闭的属性集、操作和类型。MLIR 通过Dialect(https://mlir.llvm.org/docs/LangRef/#dialects)的概念来支持这种可扩展性。Dialect在一个特定的namespace下为抽象提供了分组机制。

在MLIR里面,Operation是抽象和计算的核心单元,在许多方面与 LLVM 指定类似。具有特定于应用程序的语义,并且可以用于表示 LLVM 中的所有核心的 IR 结构:指令、globals(类似function)和模块。下面展示一个Toy语言产生的的transpose Operation。

%t_tensor = "toy.transpose"(%tensor) {inplace = true} : (tensor<2x3xf64>) -> tensor<3x2xf64> loc("example/file/path":12:1)

结构拆分解释:

  • %t_tensor:这个Operation定义的结果的名字,前面的%是避免冲突,见https://mlir.llvm.org/docs/LangRef/#identifiers-and-keywords 。一个Operation可以定义0或者多个结果(在Toy语言中,只有单结果的Operation),它们是SSA值。该名称在解析期间使用,但不是持久的(例如,它不会在 SSA 值的内存表示中进行跟踪)。
  • "toy.transpose" :Operation的名字。它应该是一个唯一的字符串,Dialect 的命名空间前缀为“.”。 这可以理解为Toy Dialect 中的transpose Operation。
  • (%tensor):零个或多个输入操作数(或参数)的列表,它们是由其它操作定义或引用块参数的 SSA 值。
  • { inplace = true }:零个或多个属性的字典,这些属性是始终为常量的特殊操作数。 在这里,我们定义了一个名为“inplace”的布尔属性,它的常量值为 true。
  • (tensor<2x3xf64>) -> tensor<3x2xf64>:函数形式表示的操作类型,前者是输入,后者是输出。<2x3xf64>号中间的内容描述了张量的尺寸2x3和张量中存储的数据类型f64,中间使用x连接。
  • loc("example/file/path":12:1):此操作的源代码中的位置。

了解了MLIR指令的基本结构后,我们把目光放到Chapter2要做什么事情上?即生成初级MLIR。我们执行下面的命令为Chapter2测试例子中的codegen.toy产生MLIR。

./toyc-ch2 ../../mlir/test/Examples/Toy/Ch2/codegen.toy -emit=mlir -mlir-print-debuginfo

其中codegen.toy的内容为:

def multiply_transpose(a, b) {return transpose(a) * transpose(b);
}def main() {var a<2, 3> = [[1, 2, 3], [4, 5, 6]];var b<2, 3> = [1, 2, 3, 4, 5, 6];var c = multiply_transpose(a, b);var d = multiply_transpose(b, a);print(d);
}

产生的MLIR为:

module  {func @multiply_transpose(%arg0: tensor<*xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":4:1), %arg1: tensor<*xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":4:1)) -> tensor<*xf64> {%0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":5:10)%1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":5:25)%2 = toy.mul %0, %1 : tensor<*xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":5:25)toy.return %2 : tensor<*xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":5:3)} loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":4:1)func @main() {%0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":9:17)%1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":9:3)%2 = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":10:17)%3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":10:3)%4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":11:11)%5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":12:11)toy.print %5 : tensor<*xf64> loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":13:3)toy.return loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":8:1)} loc("../../mlir/test/Examples/Toy/Ch2/codegen.toy":8:1)
} loc(unknown)

我们需要弄清楚codegen.toy是如何产生的MLIR文件。也即下图的AST到MLIR表达式那部分(包含Dialect)。

图源知乎法斯特豪斯,侵删

生成MLIR的流程

从AST到MLIR由是和Dialect相关的这部分

这里首先有一个MLIRGen函数负责遍历AST。具体在mlir/examples/toy/Ch2/mlir/MLIRGen.cpp文件中实现,里面有一个mlirGen函数,实现如下:

/// Dispatch codegen for the right expression subclass using RTTI.mlir::Value mlirGen(ExprAST &expr) {switch (expr.getKind()) {case toy::ExprAST::Expr_BinOp:return mlirGen(cast<BinaryExprAST>(expr));case toy::ExprAST::Expr_Var:return mlirGen(cast<VariableExprAST>(expr));case toy::ExprAST::Expr_Literal:return mlirGen(cast<LiteralExprAST>(expr));case toy::ExprAST::Expr_Call:return mlirGen(cast<CallExprAST>(expr));case toy::ExprAST::Expr_Num:return mlirGen(cast<NumberExprAST>(expr));default:emitError(loc(expr.loc()))<< "MLIR codegen encountered an unhandled expr kind '"<< Twine(expr.getKind()) << "'";return nullptr;}}

这个函数会根据AST中的节点类型递归调用其它的mlirGen子函数,并在各个子函数完成真正的转换MLIR表达式的操作。以上面codege.toytranspose(a)操作为例,对应的mlirGen子函数为:

/// Emit a call expression. It emits specific operations for the `transpose`/// builtin. Other identifiers are assumed to be user-defined functions.mlir::Value mlirGen(CallExprAST &call) {llvm::StringRef callee = call.getCallee();auto location = loc(call.loc());// Codegen the operands first.SmallVector<mlir::Value, 4> operands;for (auto &expr : call.getArgs()) {auto arg = mlirGen(*expr);if (!arg)return nullptr;operands.push_back(arg);}// Builtin calls have their custom operation, meaning this is a// straightforward emission.if (callee == "transpose") {if (call.getArgs().size() != 1) {emitError(location, "MLIR codegen encountered an error: toy.transpose ""does not accept multiple arguments");return nullptr;}return builder.create<TransposeOp>(location, operands[0]);}// Otherwise this is a call to a user-defined function. Calls to// user-defined functions are mapped to a custom call that takes the callee// name as an attribute.return builder.create<GenericCallOp>(location, callee, operands);}

我们可以看到if (callee == "transpose")这里是对函数签名进行判断,如果是transpose 那么就需要新建一个TransposeOp类型的MLIR节点,即builder.create<TransposeOp>(location, operands[0])。这行代码涉及到MLIR的Dialect和TableGen,我们详细解释一下。

在【从零开始学深度学习编译器】十一,初识MLIR 中已经说过,MLIR是通过Dialect来统一各种不同级别的IR,即负责定义各种Operation和解析,同时还具有可扩展性。在Toy语言中我们也定义了Dialect,定义这个Dialect的时候是通过TableGen规范来定义到mlir/examples/toy/Ch2/include/toy/Ops.td中的。

// Provide a definition of the 'toy' dialect in the ODS framework so that we
// can define our operations.
def Toy_Dialect : Dialect {let name = "toy";let cppNamespace = "::mlir::toy";
}

在MLIR中,Dialect和Operation(也可以说算子)的定义是框架是基于TableGen(一种声明性编程语言)规范构造的,在源码中它以.td的格式存在,在编译时会自动生成对应的C++文件,生成定义好的Dialect。使用TableGen的好处不仅是因为它是声明性的语言让新增Dialect和Operation变得简单,而且容易修改和维护。可能我解释得不是很直观,但我们可以直接结合Chapter2的代码mlir/examples/toy/Ch2/include/toy/Ops.td 来理解。后面我们会看到在Toy语言的示例中,.td文件的组成以及TableGen是如何自动解析.td生成C++代码的。

这里首先在td中定义一下Toy Dialect,并建立和Dialect的链接,它负责将后续在Toy Dialect空间下定义的所有Operation联系起来。即:

// Provide a definition of the 'toy' dialect in the ODS framework so that we
// can define our operations.
def Toy_Dialect : Dialect {let name = "toy";let cppNamespace = "::mlir::toy";
}

然后构造一个Toy_Op类代表Toy Dialect下所有Operation的基类,后面新增Operation都需要继承这个类。

// Base class for toy dialect operations. This operation inherits from the base
// `Op` class in OpBase.td, and provides:
//   * The parent dialect of the operation.
//   * The mnemonic for the operation, or the name without the dialect prefix.
//   * A list of traits for the operation.
class Toy_Op<string mnemonic, list<OpTrait> traits = []> :Op<Toy_Dialect, mnemonic, traits>;

下面给出transpose Operation的定义感受一下:

def TransposeOp : Toy_Op<"transpose"> {let summary = "transpose operation";let arguments = (ins F64Tensor:$input);let results = (outs F64Tensor);let assemblyFormat = [{`(` $input `:` type($input) `)` attr-dict `to` type(results)}];// Allow building a TransposeOp with from the input operand.let builders = [OpBuilder<(ins "Value":$input)>];// Invoke a static verify method to verify this transpose operation.let verifier = [{ return ::verify(*this); }];
}

在继承Toy_Op的基础上,还使用TableGen语法定义了描述信息,参数,值,builder,verfier这些元素。

编写完td文件之后,就可以使用mlir-tblgen工具生成C++代码,先使用下面的命令生成Dialect的C++代码:./mlir-tblgen -gen-dialect-decls llvm-project/mlir/examples/toy/Ch2/include/toy/Ops.td -I ../../mlir/include/

自动生成的Toy Dialect C++代码

把上面的命令换成./mlir-tblgen -gen-op-defs llvm-project/mlir/examples/toy/Ch2/include/toy/Ops.td -I ../../mlir/include/ 就可以生成Operation的C++代码。感兴趣的读者可自行查看。

与工具链 toyc-ch2 的联系,查看CMakeList.txt 文件(默认位置为 llvm-project/mlir/examples/toy/Ch2/include/toy):

set(LLVM_TARGET_DEFINITIONS Ops.td)
mlir_tablegen(Ops.h.inc -gen-op-decls)
mlir_tablegen(Ops.cpp.inc -gen-op-defs)
mlir_tablegen(Dialect.h.inc -gen-dialect-decls)
mlir_tablegen(Dialect.cpp.inc -gen-dialect-defs)
add_public_tablegen_target(ToyCh2OpsIncGen)

使用mlir-tblgen搭配 -gen-op-decls-gen-op-defs 选项,生成 Ops.h.inc 声明代码和 Ops.cpp.inc 定义代码,将两者作为构建工具链 toyc-ch2 的代码依赖。

总结一下,Chapter2主要介绍了MLIR中的MLIRGen,Dialect,Operation以及TableGen这几个MLIR的核心组成部分以及它们是如何相互作用的。它们的关系可以借用中科院Zhang Hongbin同学的PPT来更好的描述:

图源知乎法斯特豪斯,为了方便理解借用到这里,侵删

小结

这是阅读MLIR Toy Tutorials第一章和第二章的笔记,欢迎指出错误和不合理之处。

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

相关文章

  1. IK分词器和ElasticSearch集成使用,Java月薪过万要掌握的技能

    标准分词于IK分词器的对比 使用标准分词器查询中文: 请求 &#xff1a;GET http://localhost:9200/_analyze?analyzerstandard&prettytrue&text这是一段内容 结果&#xff1a; 使用标准分词器显然得不到我们需要的分词效果&#xff0c;这样的话就需要对中文支持良好…...

    2024/4/28 7:56:08
  2. CSDN实训任务挑战-走进Java,安装JDK及实现第一个代码。

    在没有接触编程的时候&#xff0c;觉得很神奇&#xff0c;很牛逼。两个月的学习后&#xff0c;我发现&#xff0c;&#xff0c;它是真的非常非常牛逼&#xff08;手动滑稽&#xff09;。C语言和HTML都只学了一点的我&#xff0c;对Java很是陌生&#xff0c;但又很好奇。碰巧有这…...

    2024/4/21 17:01:50
  3. 服务器镜像系统选择

    服务器镜像系统选择 什么是镜像 提供启动云服务器实例所需的所有信息。通俗地说&#xff0c;镜像就是云服务器的“装机盘”。 服务器镜像列表 服务器支持两类操作系统镜像&#xff0c;即Windows系统和Linux类系统 Linux类镜像&#xff1a;CentOS、CoreOS、Debian、FreeBSD、…...

    2024/4/21 17:01:49
  4. 知识图谱一些基础知识

    看到有关知识图谱多条问答的paper&#xff0c;对这个领域了解较少&#xff0c;看到一些资料&#xff0c;便记载 什么是知识图谱&#xff1a;是一种有向的图结构&#xff0c;由节点和有向边组成&#xff0c;节点代表“知识”&#xff0c;边代表节点与节点之间的关系。例如&…...

    2024/4/21 17:01:49
  5. MEXC Global分享:区块链技术有哪些应用场景?

    区块链最初是作为一种机制来支持BTC。为了解决数字货币的互操作性问题&#xff0c;中本聪设计了一个不可更改的分类账&#xff0c;并用加密技术将数据块链接在一起。 这个想法很快在BTC和其他Crypto中得到了验证。然而&#xff0c;区块链的应用并不仅限于此。我们只是在本文中列…...

    2024/4/21 17:01:47
  6. 一个用来在屏幕上打印出输入年份下月份对应日历的小程序:

    #define _CRT_SECURE_NO_WARNINGS //如在visual studio上编译运行&#xff0c;需加上此句 #include<stdio.h> int main() {long int year, month, i, n, flag;long long int days1 0, days2 0;printf("\n* * * * * *此程序用于生成对应年份下相应月的日历* * * * …...

    2024/4/21 17:01:46
  7. 数据结构(Java)——No1.集合框架中接口之间的关系及其含义

    数据结构&#xff08;Java&#xff09;——No1.集合框架中接口之间的关系及其含义一.集合中的接口二.接口之间的关系三.集合框架底层数据结构1.Llst&#xff08;线性结构&#xff09;2.Set&#xff08;元素不能重复&#xff09;3.Map&#xff08;用key搜索的的专家&#xff09;…...

    2024/4/21 17:01:45
  8. Hive-JDBC操作,Java常用面试题和答案

    Java是通过beeline来连接Hive的。启动beeline最重要的就是配置好hive-site.xml。 其中javax.jdo.option.ConnectionURL涉及到一个数据库&#xff0c;最好重新删掉原来的metastore数据库然后重新创建一个并初始化一下。 mysql> create database metastore; cd /usr/local/C…...

    2024/4/21 17:01:45
  9. app测试之adb常用命令

    目录 安装与卸载应用包 安装 卸载 清除应用数据与缓存 常用查看命令 查看应用包 手机信息 服务相关 进程相关 性能相关 截屏 安装与卸载应用包 安装 adb install apk包名及路径 ——注意&#xff1a;安装路径中不要出现中文&#xff0c;一定要带安装包的后缀…...

    2024/4/21 17:01:43
  10. C语言经典算法

    1. 采用递归求解的方法&#xff0c;用倒序输出字符串系统&#xff0c;用户输入字符串&#xff0c;程序运行后&#xff0c;将倒序输出。 #include "stdio.h" void reverse(){char c ;if((cgetchar())!\n){reverse();};printf("%c",c); };int main(){printf…...

    2024/4/21 17:01:42
  11. Qt5 - 插件管理(一)

    Qt5 - 插件管理(一) 最近第一次接触Qt的插件&#xff0c;也是第一次使用插件框架去实现一个独立的小软件&#xff0c;记录一下对Qt插件的理解。 我认为比较重要的概念&#xff0c;Qt中的插件&#xff0c;有两点&#xff0c;一是插件实质就是动态库&#xff0c;二是插件需要符合…...

    2024/4/21 17:01:41
  12. R语言Affinity Propagation+AP聚类实战

    R语言Affinity Propagation+AP聚类实战 目录...

    2024/4/24 20:22:20
  13. R语言KMeans聚类分析确定最优聚类簇数实战:Calinski-Harabasz准则(确定最优聚类簇数)

    R语言KMeans聚类分析确定最优聚类簇数实战:Calinski-Harabasz准则(确定最优聚类簇数) 目录...

    2024/4/25 15:28:44
  14. Nginx + Keepalived 部署Web服务

    软件环境&#xff1a; OS&#xff1a;CentOS Linux release 7.9.2009 Nginx&#xff1a;V1.20.1 Keepalived&#xff1a;V1.3.5 OS 系统安装配置 关闭iptables systemctl disable iptables 关闭firewalld systemctl disable firewalld 关闭selinux sed -i s/SELINUXenforcing…...

    2024/4/21 17:01:38
  15. R语言KMeans聚类分析确定最优聚类簇数实战:肘部法则elbow method(确定最优聚类簇数)

    R语言KMeans聚类分析确定最优聚类簇数实战:肘部法则elbow method(确定最优聚类簇数) 目录...

    2024/4/20 4:03:18
  16. 基于java爬虫的就业大数据系统设计与实现.rar(含论文+程序毕业设计)

    如果安装问题可以访问&#xff1a;https://www.bilibili.com/video/BV1S3411C7zo/ 基于java爬虫的就业大数据系统设计与实现 1 摘 要 1 1.1课题选题背景 4 1.2课题研究的意义 4 2.1功能需求分析 4 2.2系统性能分析 5 3.1系统工作流程图 5 3.2数据结构设计 7 3.3系统各功能流程图…...

    2024/4/20 14:08:19
  17. Executors类创建四种常见线程池,Tencent后台开发Java岗二面

    pool-1-thread-1 is running… pool-1-thread-1 is running… pool-1-thread-1 is running… 底层实现 /** 核心线程池大小1 最大线程池大小为1 线程过期时间为0ms LinkedBlockingQueue作为工作队列 */ public static ExecutorService newSingleThreadExecutor() { …...

    2024/4/22 7:07:35
  18. Spring反转控制

    反转控制&#xff08;IOC Inverse of Control)&#xff0c;也称为 转移控制。 控制&#xff1a;对于成员变量赋值的控制权&#xff1b;反转控制&#xff1a;把对于成员变量赋值的控制权&#xff0c;从代码中转移&#xff08;反转&#xff09;到 Spring 工厂和配置文件中完成。…...

    2024/4/20 14:08:17
  19. Java进阶—Map集合

    一、Map集合 1.Collection接口 java.util.Collection:只有一个泛型。 Collection接口定义了【单列集合】规范&#xff0c;每次存储【一个】元素&#xff0c;单个元素Collection中的集合&#xff0c;元素是【孤立存在】的&#xff08;理解为单身&#xff09;&#xff0c;向集合…...

    2024/4/21 17:01:37
  20. Centos常用命令

    文章目录一、文件夹相关1.查看目录下文件2.打开文件夹3.创建和删除文件夹4.查看及修改文件权限5. cd操作二、磁盘相关1.查看磁盘空间大小三、用户及用户组1.添加用户及用户组2.删除用户及用户组3.查看用户及用户组4.切换用户5.修改一、文件夹相关 1.查看目录下文件 ls | wc -…...

    2024/4/21 17:01:36

最新文章

  1. 服务器数据恢复—服务器重装系统导致XFS分区丢失的数据恢复案例

    服务器数据恢复环境&#xff1a; 一台服务器MD1200磁盘柜&#xff0c;通过raid卡将15块磁盘组建成一组raid5磁盘阵列。raid5阵列分配了2个lun&#xff0c;操作系统层面对lun进行分区&#xff1a;1个分区采用LVM扩容方式加入到了root_lv中&#xff0c;其余分区格式化为XFS文件系…...

    2024/4/28 12:59:32
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. Redis精品案例解析:Redis实现持久化主要有两种方式

    Redis实现持久化主要有两种方式&#xff1a;RDB&#xff08;Redis DataBase&#xff09;和AOF&#xff08;Append Only File&#xff09;。这两种方式各有优缺点&#xff0c;适用于不同的使用场景。 1. RDB持久化 RDB持久化是通过创建一个二进制的dump文件来保存当前Redis数据…...

    2024/4/25 23:00:18
  4. 流域生态系统水-碳-氮耦合过程模拟

    流域是一个相对独立的自然地理单元&#xff0c;它是以水系为纽带&#xff0c;将系统内各自然地理要素连结成一个不可分割的整体。碳和氮是陆地生态系统中最重要的两种化学元素&#xff0c;而在流域系统内&#xff0c;水-碳-氮是相互联动、不可分割的耦合体。随着流域内人类活动…...

    2024/4/27 20:57:45
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/26 18:09:39
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/28 3:28:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/26 23:05:52
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/27 4:00:35
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/27 9:01:45
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/28 1:22:35
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/25 18:39:14
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/26 23:04:58
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/26 19:46:12
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/27 11:43:08
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/27 8:32:30
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57