更全面的对比GPT4和Claude对MLIR的掌握能力

news2024/11/13 16:08:37

本文构造了20个MLIR基础概念的问题以及使用OneFlow IR转换为Tosa IR的5个代码段来评测GPT4和Claude对于MLIR的掌握能力,我的结论是对于基础概念的理解Claude整体上和GPT4持平,而在阅读相关代码片段时Claude表现出了比GPT4更强一点的理解能力。

0x0. 前言

前面的文章中以Review一段MLIR相关的Pass代码为例子,对比了ChatGPT3.5,Claude,NewBing在该任务上的理解能力。我得出的结论是在该MLIR的相关任务上,Claude>ChatGPT3.5>>Newbing,评论区有人指出GPT4 >> Clude。我感觉上次的任务设计得不是特别好,并没有充分考察ChatGPT和Claude对MLIR的一些核心概念的理解。然后我今天借到了一个GPT4的官方账号 (daquexian 大老师提供的),我打算更全面的对比一下GPT4和Claude在对MLIR的掌握能力。接下来将从MLIR基础概念以及一个OneFlow IR转换为TOSA IR的任务出发,更全面的评价GPT4和Claude对于MLIR的掌握能力。

0x1. MLIR基础概念

Q1: MLIR中的IR是什么?为什么需要多层IR?

ChatGPT4的回答:

在这里插入图片描述

Claude回答:

在这里插入图片描述

对于MLIR中的IR是什么GPT4的回答更好一些,然后对于为什么需要多层IR这个问题Claude相比于GPT4更加细节一点。

Q2. 介绍一下MLIR Dialect的概念,并描述一下Dialect的相关组件。

GPT4:

在这里插入图片描述

Claude:

在这里插入图片描述

对于这个问题,GPT4的回答非常干净准确,而Claude虽然看起来更细节一些,但是总结得让人看起来很乱。

Q3: 在MLIR中如何定义和实现一个新的Dialect?

GPT4:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

按照GPT4给出的步骤基本可以自定义一个Dialect以及相关的组件,不过现在一般对于Dialect以及Operation甚至Pass的定义都依靠了MLIR的ODS系统在相应的*.td文件中定义,并自动生成C++代码更加方便和通用。这里还可以发现GPT4在列举结果的时候,序号一直是1,并没有递增,不知道是不是BUG。

可以再看一下Claude的结果:

在这里插入图片描述

在这里插入图片描述

Claude的结果和GPT4的结果没有GPT4那么细节(比如GPT4把头文件的位置都列出来了),但是整体的步骤和GPT4基本一样,也算是比较好的理解了这个问题。

Q4: 介绍一下MLIR Dialect中的ModuleOp, FuncOp, Block

GPT4:

在这里插入图片描述

在这里插入图片描述

Claude:

在这里插入图片描述

GPT4的回答相比于Claude主要多了几个代码示例,但主体的内容两者是基本一样的。

Q5: 介绍一下MLIR Dialect中的Operation, Value, Type, Attribute

GPT4:

在这里插入图片描述

在这里插入图片描述

对概念的解释还是比较准确的,接下来看下Claude的结果:

在这里插入图片描述

在这里插入图片描述

对于这个问题,感觉Claude的回答是要比GPT4的回答好一点的。

为了进一步对比上述概念的理解,我们以MLIR的Toy Dialect示例中的transpose op定义为例,让GPT4和Claude分别详细解释下代码。

Q6: 详细解释下这行代码。%t_tensor = "toy.transpose"(%tensor) {inplace = true} : (tensor<2x3xf64>) -> tensor<3x2xf64> loc("example/file/path":12:1

GPT4:

在这里插入图片描述

在这里插入图片描述

Claude:

在这里插入图片描述

在这里插入图片描述

我们可以看到GPT4的源码分析更加细致,比如GPT4给我们解释了inplace的含义,但Claude并没有。

Q7:MLIR的Operation由Operation类和Op类的构成,请说一下它们的区别。 并说明一下ConstantOp和mlir::Operation *operation之间应该如何转换。

GPT4:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Claude:

在这里插入图片描述

在这里插入图片描述

GPT4和Claude的回答都还不错。

Q8:介绍一下MLIR Value的2个派生类BlockArgument和OpResult,并说明一下Value和mlir::Operantion *operation之间如何相互转换。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Claude:

在这里插入图片描述

在这里插入图片描述

对于Value的基础概念,GPT4和Claude都理解得不错。

Q9: 介绍一下mlir::Type,mlir::ShapedType以及mlir::TensorType

GPT4:

在这里插入图片描述

在这里插入图片描述

Claude:

在这里插入图片描述

在这里插入图片描述

就这个回答来说,Claude的回答是超越了GPT4的。它不仅为我们解释了概念,还指出这三个Type的派生类之间应该如何转换。

Q10: TensorType又可以分成RankedTensorType和UnrankedTensorType,请说明一下它们的区别以及如何判断当前的TensorType是否是Ranked。

GPT4:

在这里插入图片描述

在这里插入图片描述

Claude:

在这里插入图片描述

在这里插入图片描述
相比于GPT4,针对这个问题Claude的回答显得更好一点。主要好在它列出了RankedTensorType和UnrankedTensorType的主要成员函数并做了对比。

Q11: 介绍一下MLIR的Attribute

GPT4:
在这里插入图片描述

在这里插入图片描述
Claude:

在这里插入图片描述

在这里插入图片描述

对于Attribute的解释,我感觉Claude也是比GPT4好一点。

Q12:介绍一下MLIR的Builder和OpBuilder。

GPT4:

在这里插入图片描述

在这里插入图片描述
Claude:

在这里插入图片描述

在这里插入图片描述

个人感觉GPT4和Claude的回答都不是很完善,如果综合一下GPT4和Claude的结果会更好,这个问题双方算是平手。

Q13: 介绍一下MLIR Context和Region

GPT4:

在这里插入图片描述

在这里插入图片描述

Claude:

在这里插入图片描述

这个问题的回答,感觉Claude更加准确,并且Claude指出了使用Context和Region的一般构建流程。

我们知道在MLIR中定义OP有2种方式,一种是直接在C++定义,另外一种是基于ODS进行定义。目前主流的做法就是基于ODS也就是在一个td文件中定义OP,然后利用TableGen自动生成相应的C++代码。MLIR在OpBase.td中已经定义了一些公共的结构,接下来我们就提问GPT4和Claude是否知道这些公共的结构。

Q14: MLIR的OpBase.td有哪些公共结构

在这里插入图片描述

在这里插入图片描述

Claude:

在这里插入图片描述

我期待的回答应该类似于:

在这里插入图片描述

显然,GPT4和Claude都没有给出理想的答案,而是随机挑选了一些OpBase.td定义的类,所以这个问题并没有很好的被语言模型理解。

Q15: 解释一下TF Dialect中对AvgPool Op使用ODS进行定义涉及到的TableGen语法,AvgPool Op定义的代码如下

# https://github.com/tensorflow/tensorflow/blob/master/tensorflow/compiler/mlir/tensorflow/ir/tf_generated_ops.td#L965
def TF_AvgPoolOp : TF_Op<"AvgPool", [Pure]> {
  let summary = "Performs average pooling on the input.";

  let description = [{
Each entry in `output` is the mean of the corresponding size `ksize`
window in `value`.
  }];

  let arguments = (ins
    Arg<TF_FloatTensor, [{4-D with shape `[batch, height, width, channels]`.}]>:$value,

    ConfinedAttr<I64ArrayAttr, [ArrayMinCount<4>]>:$ksize,
    ConfinedAttr<I64ArrayAttr, [ArrayMinCount<4>]>:$strides,
    TF_AnyStrAttrOf<["SAME", "VALID"]>:$padding,
    DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, "\"NHWC\"">:$data_format
  );

  let results = (outs
    Res<TF_FloatTensor, [{The average pooled output tensor.}]>:$output
  );

  TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>;
}

GPT4:

在这里插入图片描述

Claude:

在这里插入图片描述

在这里插入图片描述

GPT4和Claude的结果比较类似,都是逐行解析了涉及到的TableGen语法。

Q16: 请解释一下MLIR中的Bufferization

GPT4:

在这里插入图片描述

Claude:

在这里插入图片描述

在这里插入图片描述

GPT4的回答宏观一些,Claude的回答更具体一些,都有优点。

Q17: 对于将分散的memref.alloc操作优化合并成单一的memref.alloc统一分配并通过类似memref.subview进行复用,你有什么建议吗,有现成的类似的pass实现吗

GPT4:

在这里插入图片描述

在这里插入图片描述

Claude:

在这里插入图片描述

对于这个问题,GPT4总结得比Claude更细一些。

Q18: 讲一下MLIR中One-Shot Bufferize设计的目的和目前成熟的应用

GPT4:

在这里插入图片描述

Claude:

在这里插入图片描述

两种回答差不多,不分高下。

Q19: https://mlir.llvm.org/docs/Bufferization/ 这个网页你能解读一下吗

GPT4:

在这里插入图片描述

Claude:

在这里插入图片描述

GPT4的总结稍微更贴合网页一些,但是自己去浏览网页可以发现还是有一些细节被漏掉了,如果要学习Bufferization还是建议去看下原始的网页。

Q20: 解释下linalg的算子融合算法

GPT4:

在这里插入图片描述
Claude:

在这里插入图片描述

对Linalg的学习有限,个人感觉这两个答案都是比较宏观的,需要查看Linalg的文档或者代码进一步获取相关信息。

上面一共问了20个问题,我个人感觉GPT4相比于Claude并没有很大的优势,我的初步结论是就MLIR的基础概念理解来看,GPT4和Claude几乎打成平手。

0x2. 代码阅读

这一节,我以OneFlow中的OneFlow Dialect中的Op转换为TOSA Dialect中的Op为例子,对比一下GPT4和Claude对相关代码的理解能力。这部分代码在 https://github.com/Oneflow-Inc/oneflow/blob/master/oneflow/ir/lib/OneFlow/Conversion/OneFlowToTosa.cpp 这个c++文件中。

Code 1

解释一下

Type convertToSignless(MLIRContext* context, Type type) {
  if (auto ranked_tensor = type.dyn_cast<RankedTensorType>()) {
    if (auto intTy = ranked_tensor.getElementType().dyn_cast<IntegerType>()) {
      if (!intTy.isSignless()) {
        return RankedTensorType::get(
            ranked_tensor.getShape(),
            IntegerType::get(context, intTy.getWidth(),
                             mlir::IntegerType::SignednessSemantics::Signless));
      }
    }
  }
  return type;
}

FunctionType convertToSignlessFuncType(MLIRContext* context, FunctionType funcType) {
  llvm::SmallVector<Type, 4> inputs;
  llvm::SmallVector<Type, 4> results;
  for (auto arg : funcType.getInputs()) { inputs.push_back(convertToSignless(context, arg)); }
  for (auto res : funcType.getResults()) { results.push_back(convertToSignless(context, res)); }
  return FunctionType::get(context, inputs, results);
}

GPT4:

在这里插入图片描述

Claude:

在这里插入图片描述

GPT4和Claude对这段代码的解释基本相同,并且都是正确的。

Code2
解释一下:

bool isSignLessTensorOrOther(Type type) {
  if (auto ranked_tensor = type.dyn_cast<RankedTensorType>()) {
    if (auto intTy = ranked_tensor.getElementType().dyn_cast<IntegerType>()) {
      if (intTy.isUnsigned()) { return false; }
      if (intTy.isSigned()) { return false; }
    }
  }
  return true;
}
bool allSignless(mlir::TypeRange types) {
  for (auto type : types) {
    if (!isSignLessTensorOrOther(type)) { return false; }
  }
  return true;
}

bool allSignless(FunctionType funcType) {
  for (auto arg : funcType.getInputs()) {
    if (!isSignLessTensorOrOther(arg)) { return false; }
  }
  for (auto res : funcType.getResults()) {
    if (!isSignLessTensorOrOther(res)) { return false; }
  }
  return true;
}

GPT4:

在这里插入图片描述

Claude:

在这里插入图片描述

GPT4和Claude的结果也比较类似,但Claude有个优点就是它对每个函数都给出了一个例子,可以帮助读者更方便的去理解这段代码的含义。

Code3

解释一下:

Value CreateTransposeValue(Location& loc, ConversionPatternRewriter& rewriter, Value input,
                           ArrayRef<int32_t> perms) {
  int perms_size = perms.size();
  auto transpose_perms = rewriter.create<tosa::ConstOp>(
      loc, RankedTensorType::get({perms_size}, rewriter.getI32Type()),
      rewriter.getI32TensorAttr(perms));
  const auto shape_type = input.getType().cast<ShapedType>();
  std::vector<int64_t> ranked_type;
  for (const auto& index : perms) ranked_type.push_back(shape_type.getDimSize(index));
  return rewriter.create<tosa::TransposeOp>(
      loc, RankedTensorType::get(ranked_type, shape_type.getElementType()), input, transpose_perms);
};

RankedTensorType CreateTransposeType(ShapedType output, ArrayRef<int32_t> perms) {
  std::vector<int64_t> ranked_type;
  for (auto index : perms) ranked_type.push_back(output.getDimSize(index));
  return RankedTensorType::get(ranked_type, output.getElementType());
};

GPT4:

在这里插入图片描述

Claude:

在这里插入图片描述

相比之下,感觉Claude的解释可以胜出。

Code4

解释一下:

Value CreateBNOp(Location loc, ConversionPatternRewriter& rewriter, Type output_type, Value x,
                 Value mean, Value variance, Value epsilon, Value gamma, Value beta) {
  // sub_op = sub(input, mean)
  auto sub_op0 = rewriter.create<tosa::SubOp>(loc, output_type, x, mean);
  // add_op0 = add(var, epsilon)
  auto add_op0 = rewriter.create<tosa::AddOp>(loc, variance.getType(), variance, epsilon);
  // rsqrt_op = rsqrt(add_op0)
  auto rsqrt_op = rewriter.create<tosa::RsqrtOp>(loc, variance.getType(), add_op0);
  // op4 = mul(sub_op, rsqrt_op)
  auto mul_op0 = rewriter.create<tosa::MulOp>(loc, output_type, sub_op0, rsqrt_op, 0);
  // op5 = mul(mul_op0, gamma)
  auto mul_op1 = rewriter.create<tosa::MulOp>(loc, output_type, mul_op0, gamma, 0);
  // op6 = add(mul_op1, beta)
  Value batch_norm = rewriter.create<tosa::AddOp>(loc, output_type, mul_op1, beta);
  return batch_norm;
};

GPT4:

在这里插入图片描述

Claude:

在这里插入图片描述

感觉GPT4和Claude对代码的理解是一样的。

Code5

再看一个卷积Op,解释一下:

struct Conv2DOpLowering final : public OpConversionPattern<Conv2DOp> {
 public:
  using OpConversionPattern<Conv2DOp>::OpConversionPattern;
  LogicalResult matchAndRewrite(Conv2DOp op, OpAdaptor adaptor,
                                ConversionPatternRewriter& rewriter) const override {
    auto get_pair_int64_from_array = [](ArrayAttr arr) -> std::pair<int64_t, int64_t> {
      return {arr.getValue()[0].cast<IntegerAttr>().getSInt(),
              arr.getValue()[1].cast<IntegerAttr>().getSInt()};
    };

    auto stride_pairs = get_pair_int64_from_array(op.getStrides());
    auto pad_pairs = get_pair_int64_from_array(op.getPaddingBeforeAttr());
    auto dilation_pairs = get_pair_int64_from_array(op.getDilationRate());

    const auto pad = rewriter.getDenseI64ArrayAttr(
        {pad_pairs.first, pad_pairs.second, pad_pairs.first, pad_pairs.second});
    const auto stride = rewriter.getDenseI64ArrayAttr({stride_pairs.first, stride_pairs.second});
    const auto dilation =
        rewriter.getDenseI64ArrayAttr({dilation_pairs.first, dilation_pairs.second});

    auto bias = op.getBias();
    auto loc = op.getLoc();
    if (!bias) {
      const auto output_shape = op.getOut().getType().cast<ShapedType>();
      // support nhwc
      const auto output_channels = output_shape.getDimSize(op.IsNCHW() ? 1 : 3);
      const auto bias_elem_type = output_shape.getElementType();
      const auto type = RankedTensorType::get(output_channels, bias_elem_type);
      bias = rewriter.create<tosa::ConstOp>(
          op.getLoc(), type, DenseElementsAttr::get(type, rewriter.getZeroAttr(bias_elem_type)));
    }

    auto in = op.getIn();
    auto weight = op.getWeight();
    auto out_type = op.getOut().getType().cast<ShapedType>();
    if (out_type.getRank() != 4) {
      LOG(FATAL) << "Failed to lowering oneflow op";
      op->dump();
    }
    // support nhwc
    if (op.IsNCHW()) {
      const auto perms = {0, 2, 3, 1};
      const auto reverse_perms = {0, 3, 1, 2};
      in = CreateTransposeValue(loc, rewriter, in, perms);
      weight = CreateTransposeValue(loc, rewriter, weight, perms);
      out_type = CreateTransposeType(out_type, perms);
      auto conv2d =
          rewriter.create<tosa::Conv2DOp>(loc, out_type, in, weight, bias, pad, stride, dilation);

      auto res = CreateTransposeValue(loc, rewriter, conv2d, reverse_perms);
      rewriter.replaceOp(op, {res});
    } else {
      rewriter.replaceOpWithNewOp<tosa::Conv2DOp>(op, out_type, in, weight, bias, pad, stride,
                                                  dilation);
    }
    return success();
  }
};

GPT4:

在这里插入图片描述

Claude:

在这里插入图片描述

我们再问一下,为什么format为"NHWC"的时候要加transpose操作?

在这里插入图片描述

在这里插入图片描述

可以看到Claude理解了我的问题,并指出这是因为Tosa的conv2d不支持nhwc数据格式,所以需要加transpose。而GPT4在这个问题上就没有理解我的意思并字面意义的重复了我的问题。

0x3. 总结

本文构造了20个MLIR基础概念的问题以及使用OneFlow IR转换为Tosa IR的5个代码段来评测GPT4和Claude对于MLIR的掌握能力,我的结论是对于基础概念的理解Claude整体上和GPT4持平,而在阅读相关代码片段时Claude表现出了比GPT4更强一点的理解能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/448536.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python】读取r语言数据+NMF算法(完整代码+详细注释)

目录 依赖库代码功能完整代码总结 欢迎关注 『Python』 系列&#xff0c;持续更新中 欢迎关注 『Python』 系列&#xff0c;持续更新中 算法部分源码是我的数模兄弟想要深入研究nmf算法方面的内容发给我让我跑的 参考自博文 https://blog.csdn.net/atease0001/article/details/…

计及光伏电站快速无功响应特性的分布式电源优化配置方法(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …

JS的函数定义和参数

文章目录 一、JavaScript 函数定义二、JavaScript 函数参数总结 一、JavaScript 函数定义 JavaScript 使用关键字 function 定义函数。 函数可以通过声明定义&#xff0c;也可以是一个表达式。 函数声明 function functionName(parameters) {执行的代码 }函数声明后不会立即…

【C++内联函数】

目录 前言内联函数的概念内联函数的特性内联函数的总结 前言 假设有这样的一个场景&#xff0c;有一个代码量不足三行的函数被调用了一万次&#xff0c;现在让你做优化&#xff0c;你会怎么考虑优化&#xff1f; 我们都知道函数调用是有时间和空间开销的。程序在执行一个函数之…

Ansys Lumerical | 使用 STACK 仿真抗反射偏振器件

1、说明 在本示例中&#xff0c;我们将展示使用 Lumerical STACK 求解器来设计抗反射圆偏振器&#xff0c;以减少 OLED 显示器的环境光反射。 2、综述 OLED 显示器的底部金属电极可以用于增强光提取效率&#xff0c;然而它也会带来环境光反射的不利影响&#xff0c;导致显示器在…

深度学习-基础(二)-numpy中的轴操作

背景 使用Pytorch进行学习&#xff0c;少不了跟numpy打交道&#xff0c;比如数据集中去除通道reduction只有做加法运算等&#xff0c;但是numpy轴操作&#xff0c;很少有人讲清楚&#xff0c;此处加以梳理。 轴的概念 轴用来为超过一维的数组定义的属性&#xff0c;二维数据…

【Atlas500】华为500小站预配置

目录 基础配置解决配置能力项未开启问题 基础配置 1.网线连接盒子 2.1口IP:192.168.2.111 2口IP&#xff1a;192.168.3.111 3.登临网页https://192.168.2.111 输入用户名和密码&#xff08;管理端用户&#xff09;。 ● 默认用户名&#xff1a;admin ● 默认密码&#xff1a;H…

Eclipse安装插件及所有插件下载地址汇总

Eclipse安装插件及所有插件下载地址汇总 插件的意义安装插件各插件下载地址汇总kepler&#xff08;Eclipse配置本地安装好的Tomcat时使用的插件&#xff09;另一个插件名称 插件的意义 自认是为了解耦&#xff0c;使使用eclipse的人可以依据自己所需&#xff0c;有针对性的下载…

MySQL_第04章_运算符

第04章_运算符 讲师&#xff1a;尚硅谷 - 宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a; http://www.atguigu.com 1. 算术运算符 算术运算符主要用于数学运算&#xff0c;其可以连接运算符前后的两个数值或表达式&#xff0c;对数值或表达式…

Node第三方包 【mysql2】

文章目录 &#x1f31f;前言&#x1f31f;访问数据库&#x1f31f;MySQL驱动&#x1f31f;mysql2&#x1f31f;安装 &#x1f31f;方法&#x1f31f;连接数据库&#x1f31f;通过 query() 方法执行SQL语句&#x1f31f;通过 execute() 方法执行SQL语句 &#x1f31f;使用连接池…

研报精选230419

目录 【行业230419东吴证券】AACR2023本土药企临床进展&#xff1a;“秒懂”全球创新药系列研究之会议追踪 【行业230419浙商证券】大制造行业估值手册&#xff1a;周度数据跟踪 【行业230419东方财富证券】2023上海车展前瞻&#xff1a;自主争先&#xff0c;迎接智能电动新时代…

#Chrome扩展程序开发教程--03:Manifest

#Chrome扩展程序开发教程--03&#xff1a;Manifest 引言1、基本介绍2、必须属性3、重要属性3.1、permissions、host_permissions、optional_permissions、optional_host_permissions3.2、background3.3、content_scripts3.4、action3.5、options_page3.6、options_ui3.7、icons…

C++ Linux Web Server 面试基础篇-操作系统(四、线程通信)

⭐️我叫忆_恒心&#xff0c;一名喜欢书写博客的在读研究生&#x1f468;‍&#x1f393;。 如果觉得本文能帮到您&#xff0c;麻烦点个赞&#x1f44d;呗&#xff01; 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧&#xff0c;喜欢的小伙伴给个三…

TiDB实战篇-Data Migration (DM) 同步数据

目录 简介 原理 任务管理 ​编辑同步拓扑示例 使用场景 限制 硬件配置 安装&升级 部署 生成配置文件 生成配置文件模板 更具自身的机器修改 部署 启动集群&查看集群 实战 上游数据库前提 配置mysql的相关配置 编写DM的MySQL相关配置 把MySQL和DM …

【JavaEE】Bean的作用域和生命周期

目录 Bean的作用域 作用域分类 设置作用域 通过注解设置 通过配置文件设置 Bean的生命周期 Bean的作用域 Bean的作用域是指&#xff1a;在整个Spring容器中Bean的行为模式。这个模式有六种。 作用域分类 singleton&#xff1a;单例作用域。 在这个模式下&#xff0c;容器…

网络地址转换应用

如图所示,企业使用一台AR 路由器作为出口设备,路由器配置NAT Outbound为私网用户提供访问Internet服务,同时配置NAT Server将私网WEB服务器发布到公网上,对外网用户提供服务。运营商仅为该单位分配了一个公网IP,此地址既作为AR出接口的IP地址,也作为NAT Outbound和NAT Se…

【Atlas500】华为Atals MindStudio配置指南

目录 安装推理用ubuntu版docker配置docker内的ssh服务安装ubuntu系统中的依赖项&#xff1a;检查root用户的umask安装依赖项安装CANN连接到CANN Setting 安装推理用ubuntu版docker 华为的atlas500自带的欧拉系统是一个裁剪系统&#xff0c;一般通过在其上运行官方的ubuntu dock…

【消息队列】Kafka高水位和Leader Epoch原理

什么是高水位 首先高水位也就是HW&#xff0c;而对应的有LEO&#xff0c;其实这都是Kafka副本中针对位移的概念&#xff0c;其目的就是为了保证多副本间数据的一致性。 LEO &#xff08;Log End Offet&#xff09;&#xff1a;每个副本的最后一个offset&#xff0c;LEO其实就是…

你猜我猜不猜 (猜数字游戏) 快来小玩一把叭

&#x1f929;本文作者&#xff1a;大家好&#xff0c;我是paperjie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 &#x1f970;内容专栏&#xff1a;这里是《C语言》专栏&#xff0c;笔者用重金(时间和精力)打造&#xff0c;将C语言知识一网打尽&#xff0c;希望可…

解决Vue热更新失效问题

解决Vue热更新失效 一、问题描述二、出现原因三、解决方案四、总结 &#x1f680; 欢迎访问我的个人博客&#xff1a;https://wk-blog.vip 一、问题描述 之前在本地测试Vue项目时&#xff0c;是可以热更新的&#xff0c;但是最近一段时间发现Vue的热更新失效了。然后通过vs co…