Triton教程 --- Triton架构

news2024/10/6 20:28:47

Triton教程 —Triton架构

在这里插入图片描述

文章目录

  • Triton教程 ---Triton架构
    • 并发模型执行
    • 模型和调度器
      • 无状态模型
      • 状态模型
      • 控制输入
      • 隐式状态管理
      • 状态初始化
      • 调度策略
        • 直接的
        • Oldest
      • 合奏模型

下图显示了 Triton 推理服务器的高级架构。 模型存储库是一个基于文件系统的模型存储库,Triton 将使其可用于推理。 推理请求通过 HTTP/REST 或 GRPC 或 C API 到达服务器,然后路由到适当的每个模型调度程序。 Triton 实现了多种调度和批处理算法,可以在逐个模型的基础上进行配置。 每个模型的调度器可选择执行推理请求的批处理,然后将请求传递给与模型类型对应的后端。 后端使用批处理请求中提供的输入执行推理以生成请求的输出。 然后返回输出。

Triton 支持后端 C API,允许 Triton 扩展新功能,例如自定义预处理和后处理操作,甚至是新的深度学习框架。

Triton 提供的模型可以通过专用模型管理 API 查询和控制,该 API 可通过 HTTP/REST 或 GRPC 协议或 C API 获得。

就绪性和活性健康端点和利用率、吞吐量和延迟指标简化了 Triton 与部署框架(如 Kubernetes)的集成。

并发模型执行

Triton 架构允许多个模型或同一模型的多个实例在同一系统上并行执行。 系统可能有零个、一个或多个 GPU。 下图显示了具有两个模型的示例; 模型 0 和模型 1。 假设 Triton 当前没有处理任何请求,当两个请求同时到达时,每个模型一个,Triton 立即将它们都调度到 GPU 上,GPU 的硬件调度程序开始并行处理这两个计算。 在系统 CPU 上执行的模型由 Triton 类似地处理,除了 CPU 线程执行每个模型的调度由系统的操作系统处理。

默认情况下,如果同一模型的多个请求同时到达,Triton 将通过在 GPU 上一次只调度一个来序列化它们的执行,如下图所示。

Triton 提供了一个名为 instance-group 的模型配置选项,它允许每个模型指定应该允许该模型并行执行的次数。 每个这样启用的并行执行都称为一个实例。 默认情况下,Triton 为系统中每个可用的 GPU 为每个模型提供一个实例。 通过使用模型配置中的 instance_group 字段,可以更改模型的执行实例数。 下图显示了当 model1 配置为允许三个实例时的模型执行。 如图所示,前三个 model1 推理请求立即并行执行。 第四个 model1 推理请求必须等到前三个执行中的一个执行完成才能开始。

模型和调度器

Triton 支持多种调度和批处理算法,可以为每个模型独立选择。 本节介绍无状态、有状态和集成模型,以及 Triton 如何提供调度程序来支持这些模型类型。 对于给定的模型,调度程序的选择和配置是通过模型的配置文件完成的。

无状态模型

关于 Triton 的调度程序,无状态模型不会在推理请求之间维护状态。 在无状态模型上执行的每个推理都独立于使用该模型的所有其他推理。

无状态模型的示例是 CNN,例如图像分类和对象检测。 默认调度程序或动态批处理程序可用作这些无状态模型的调度程序。

RNN 和具有内部存储器的类似模型可以是无状态的,只要它们维护的状态不跨越推理请求。 例如,如果推理请求的批次之间未携带内部状态,则 Triton 认为迭代批次中所有元素的 RNN 是无状态的。 默认调度程序可用于这些无状态模型。 不能使用动态批处理程序,因为模型通常不希望批处理代表多个推理请求。

状态模型

关于 Triton 的调度程序,有状态模型确实会在推理请求之间维护状态。 该模型需要多个推理请求,这些请求一起形成一系列推理,这些推理必须路由到同一模型实例,以便模型维护的状态得到正确更新。 此外,该模型可能要求 Triton 提供控制信号,例如指示序列的开始和结束。

序列批处理程序必须用于这些有状态模型。 如下所述,序列批处理程序可确保将序列中的所有推理请求路由到同一模型实例,以便模型可以正确维护状态。 序列批处理程序还与模型通信以指示序列何时开始、序列何时结束、序列何时具有准备好执行的推理请求以及序列的相关 ID。

在对有状态模型发出推理请求时,客户端应用程序必须为序列中的所有请求提供相同的关联 ID,并且还必须标记序列的开始和结束。 关联 ID 允许 Triton 识别请求属于同一序列。

控制输入

为了使有状态模型与序列批处理程序一起正确运行,模型通常必须接受一个或多个 Triton 用来与模型通信的控制输入张量。 模型配置的 ModelSequenceBatching::Control 部分指示模型如何公开序列批处理程序应该用于这些控件的张量。 所有控件都是可选的。 下面是模型配置的一部分,显示了所有可用控制信号的示例配置。

sequence_batching {
  control_input [
    {
      name: "START"
      control [
        {
          kind: CONTROL_SEQUENCE_START
          fp32_false_true: [ 0, 1 ]
        }
      ]
    },
    {
      name: "END"
      control [
        {
          kind: CONTROL_SEQUENCE_END
          fp32_false_true: [ 0, 1 ]
        }
      ]
    },
    {
      name: "READY"
      control [
        {
          kind: CONTROL_SEQUENCE_READY
          fp32_false_true: [ 0, 1 ]
        }
      ]
    },
    {
      name: "CORRID"
      control [
        {
          kind: CONTROL_SEQUENCE_CORRID
          data_type: TYPE_UINT64
        }
      ]
    }
  ]
}
  • Start:开始输入张量在配置中使用 CONTROL_SEQUENCE_START 指定。 示例配置表明模型有一个名为 START 的输入张量,其数据类型为 32 位浮点数。 序列批处理程序将在对模型执行推理时定义此张量。 START 张量必须是一维的,大小等于批量大小。 张量中的每个元素指示相应批槽中的序列是否开始。 在示例配置中,fp32_false_true 表示序列开始由张量元素等于 1 表示,非开始由张量元素等于 0 表示。

  • End:结束输入张量在配置中使用 CONTROL_SEQUENCE_END 指定。 示例配置表明模型有一个名为 END 的输入张量,具有 32 位浮点数据类型。 序列批处理程序将在对模型执行推理时定义此张量。 END 张量必须是一维的,大小等于批量大小。 张量中的每个元素指示相应批槽中的序列是否结束。 在示例配置中,fp32_false_true表示一个序列结束由张量元素等于1表示,非结束由张量元素等于0表示。

  • Ready:就绪输入张量在配置中使用 CONTROL_SEQUENCE_READY 指定。 示例配置表明模型有一个名为 READY 的输入张量,其数据类型为 32 位浮点数。 序列批处理程序将在对模型执行推理时定义此张量。 READY 张量必须是一维的,其大小等于批量大小。 张量中的每个元素指示相应批槽中的序列是否具有准备好进行推理的推理请求。 在示例配置中,fp32_false_true 表示序列就绪由张量元素等于 1 表示,非就绪由张量元素等于 0 表示。

  • Correlation ID:关联 ID 输入张量在配置中使用 CONTROL_SEQUENCE_CORRID 指定。 示例配置表明模型有一个名为 CORRID 的输入张量,其数据类型为无符号 64 位整数。 序列批处理程序将在对模型执行推理时定义此张量。 CORRID 张量必须是一维的,大小等于批量大小。 张量中的每个元素表示相应批槽中序列的相关 ID。

隐式状态管理

隐式状态管理允许有状态模型将其状态存储在 Triton 中。 当使用隐式状态时,有状态模型不需要在模型内部存储推理所需的状态。

下面是模型配置的一部分,表明模型正在使用隐式状态。

sequence_batching {
  state [
    {
      input_name: "INPUT_STATE"
      output_name: "OUTPUT_STATE"
      data_type: TYPE_INT32
      dims: [ -1 ]
    }
  ]
}

sequence_batching 设置中的状态部分用于指示模型正在使用隐式状态。 input_name 字段指定将包含输入状态的输入张量的名称。 output_name 字段描述了包含输出状态的模型产生的输出张量的名称。 模型在序列中第 i 个请求中提供的输出状态将用作第 i+1 个请求中的输入状态。 dims 字段指定状态张量的维度。 当 dims 字段包含可变大小的维度时,输入状态和输出状态的形状不必匹配。

出于调试目的,客户端可以请求输出状态。 为了允许客户端请求输出状态,模型配置的输出部分必须将输出状态列为模型输出之一。 请注意,由于必须传输额外的张量,从客户端请求输出状态可能会增加请求延迟。

隐式状态管理需要后端支持。 目前只有 onnxruntime_backend 和 tensorrt_backend 支持隐式状态。

状态初始化

默认情况下,序列中的起始请求包含输入状态的未初始化数据。 模型可以使用请求中的开始标志来检测新序列的开始,并通过在模型输出中提供初始状态来初始化模型状态。 如果模型状态描述中的 dims 部分包含可变大小的维度,Triton 将为每个可变大小的维度使用 1 来启动请求。 对于序列中的其他非启动请求,输入状态是序列中前一个请求的输出状态。 对于使用隐式状态的示例 ONNX 模型,您可以参考此生成脚本中的 create_onnx_modelfile_wo_initial_state() 生成的 onnx 模型。 这是一个简单的累加器模型,它使用隐式状态将请求的部分总和存储在 Triton 的序列中。 对于状态初始化,如果请求正在启动,模型会将“OUTPUT_STATE”设置为等于“INPUT”张量。 对于非启动请求,它将“OUTPUT_STATE”张量设置为“INPUT”和“INPUT_STATE”张量之和。

除了上面讨论的默认状态初始化之外,Triton 还提供了另外两种初始化状态的机制。

从零初始化状态。

下面是一个从零开始初始化状态的例子。


sequence_batching {
  state [
    {
      input_name: "INPUT_STATE"
      output_name: "OUTPUT_STATE"
      data_type: TYPE_INT32
      dims: [ -1 ]
      initial_state: {
       data_type: TYPE_INT32
       dims: [ 1 ]
       zero_data: true
       name: "initial state"
      }
    }
  ]
}

请注意,在上面的示例中,状态描述中的可变维度被转换为固定大小的维度。

从文件初始化状态
为了从文件初始化状态,您需要在模型目录下创建一个名为“initial_state”的目录。 需要在 data_file 字段中提供该目录下包含初始状态的文件。 存储在该文件中的数据将以行优先顺序用作初始状态。 下面是一个从文件初始化状态的示例状态描述。

sequence_batching {
  state [
    {
      input_name: "INPUT_STATE"
      output_name: "OUTPUT_STATE"
      data_type: TYPE_INT32
      dims: [ -1 ]
      initial_state: {
       data_type: TYPE_INT32
       dims: [ 1 ]
       data_file: "initial_state_data"
       name: "initial state"
      }
    }
  ]
}

调度策略

在决定如何对路由到同一模型实例的序列进行批处理时,序列批处理程序可以采用两种调度策略之一。 这些策略是直接且最古老的。

直接的

使用直接调度策略,序列批处理程序不仅确保序列中的所有推理请求都被路由到同一模型实例,而且每个序列都被路由到模型实例中的专用批处理槽。 当模型维护每个批处理槽的状态并期望将给定序列的所有推理请求路由到同一槽以便正确更新状态时,需要此策略。

作为使用直接调度策略的序列批处理程序的示例,假设一个 TensorRT 有状态模型具有以下模型配置。

name: "direct_stateful_model"
platform: "tensorrt_plan"
max_batch_size: 2
sequence_batching {
  max_sequence_idle_microseconds: 5000000
  direct { }
  control_input [
    {
      name: "START"
      control [
        {
          kind: CONTROL_SEQUENCE_START
          fp32_false_true: [ 0, 1 ]
        }
      ]
    },
    {
      name: "READY"
      control [
        {
          kind: CONTROL_SEQUENCE_READY
          fp32_false_true: [ 0, 1 ]
        }
      ]
    }
  ]
}
input [
  {
    name: "INPUT"
    data_type: TYPE_FP32
    dims: [ 100, 100 ]
  }
]
output [
  {
    name: "OUTPUT"
    data_type: TYPE_FP32
    dims: [ 10 ]
  }
]
instance_group [
  {
    count: 2
  }
]

sequence_batching 部分指示模型应使用序列批处理程序和直接调度策略。 在此示例中,模型仅需要来自序列批处理程序的启动和就绪控制输入,因此仅列出这些控制。 instance_group 表示应该实例化模型的两个实例,max_batch_size 表示每个实例都应该执行批量大小为 2 的推理。 下图显示了序列批处理程序和此配置指定的推理资源的表示。

每个模型实例都维护每个批处理槽的状态,并期望将给定序列的所有推理请求路由到同一个槽,以便正确更新状态。 对于这个例子,这意味着 Triton 最多可以同时对四个序列进行推理。

使用直接调度策略,序列批处理程序:

  • 识别推理请求何时开始新序列并为该序列分配批处理槽。 如果没有可用于新序列的批处理槽,Triton 会将推理请求放入待办事项列表中。

  • 识别推理请求何时是具有分配的批处理槽的序列的一部分,并将请求路由到该槽。

  • 识别推理请求何时是积压中序列的一部分,并将请求放入积压中。

  • 识别序列中的最后一个推理请求何时完成。 该序列占用的批处理槽会立即重新分配给积压中的序列,或者如果没有积压,则为未来的序列释放。

下图显示了如何使用直接调度策略将多个序列调度到模型实例上。 左图显示了到达 Triton 的几个请求序列。 每个序列可以由任意数量的推理请求组成,并且这些单独的推理请求可以相对于其他序列中的推理请求以任何顺序到达,除了右侧显示的执行顺序假定序列 0 的第一个推理请求到达之前 序列 1-5 中的任何推理请求,序列 1 的第一个推理请求在序列 2-5 中的任何推理请求之前到达,依此类推。

该图的右侧显示了推理请求序列如何随着时间的推移被调度到模型实例上。

下图显示了序列批处理程序使用控制输入张量与模型进行通信。 该图显示了分配给模型实例中两个批槽的两个序列。 每个序列的推理请求随时间到达。 START 和 READY 行显示用于模型每次执行的输入张量值。 随着时间的推移,会发生以下情况:

  • 第一个请求到达 slot0 中的序列。 假设模型实例尚未执行推理,序列调度程序会立即调度模型实例执行,因为推理请求可用。

  • 这是序列中的第一个请求,因此 START 张量中的相应元素设置为 1。slot1 中没有可用请求,因此 READY 张量仅显示 slot0 就绪。

  • 推理完成后,序列调度程序发现任何批处理槽中都没有可用请求,因此模型实例处于空闲状态。

  • 接下来,两个推理请求及时到达,以便序列调度程序看到它们在各自的批处理槽中都可用。 调度程序立即安排模型实例执行批量大小为 2 的推理,并使用 START 和 READY 来表明两个槽都有可用的推理请求,但只有槽 1 是新序列的开始。

  • 对于其他推理请求,处理以类似的方式继续。

Oldest

使用 Oldest 调度策略,序列批处理程序确保序列中的所有推理请求都被路由到相同的模型实例,然后使用动态批处理程序将来自不同序列的多个推理一起批处理成一起推理的批处理。 使用此策略,模型通常必须使用 CONTROL_SEQUENCE_CORRID 控件,以便它知道批处理中的每个推理请求属于哪个序列。 通常不需要 CONTROL_SEQUENCE_READY 控件,因为批处理中的所有推理将始终准备好进行推理。

作为使用Oldest调度策略的序列批处理程序的示例,假设有一个具有以下模型配置的有状态模型:


name: "oldest_stateful_model"
platform: "tensorflow_savedmodel"
max_batch_size: 2
sequence_batching {
  max_sequence_idle_microseconds: 5000000
  oldest
    {
      max_candidate_sequences: 4
    }
  control_input [
    {
      name: "START"
      control [
        {
          kind: CONTROL_SEQUENCE_START
          fp32_false_true: [ 0, 1 ]
        }
      ]
    },
    {
      name: "END"
      control [
        {
          kind: CONTROL_SEQUENCE_END
          fp32_false_true: [ 0, 1 ]
        }
      ]
    },
    {
      name: "CORRID"
      control [
        {
          kind: CONTROL_SEQUENCE_CORRID
          data_type: TYPE_UINT64
        }
      ]
    }
  ]
}
input [
  {
    name: "INPUT"
    data_type: TYPE_FP32
    dims: [ 100, 100 ]
  }
]
output [
  {
    name: "OUTPUT"
    data_type: TYPE_FP32
    dims: [ 10 ]
  }
]

sequence_batching 部分指示模型应使用序列批处理程序和最旧的调度策略。 配置 Oldest 策略,以便序列批处理程序最多保留 4 个活动候选序列,它更愿意从中形成大小为 2 的动态批处理。在此示例中,模型需要来自序列批处理程序的开始、结束和相关 ID 控制输入。 下图显示了序列批处理程序和此配置指定的推理资源的表示。

使用 Oldest 调度策略,序列批处理程序:

  • 识别推理请求何时启动新序列并尝试查找具有候选序列空间的模型实例。 如果没有模型实例有空间容纳新的候选序列,Triton 会将推理请求放入待办事项列表中。

  • 识别推理请求何时是某个模型实例中已经是候选序列的序列的一部分,并将请求路由到该模型实例。

  • 识别推理请求何时是积压中序列的一部分,并将请求放入积压中。

  • 识别序列中的最后一个推理请求何时完成。 模型实例立即从backlog中移除一个序列,使其成为模型实例中的候选序列,或者如果没有backlog,则记录该模型实例可以处理未来的序列。

下图显示了如何将多个序列调度到上述示例配置指定的模型实例上。 左图显示了到达 Triton 的四个请求序列。 如图所示,每个序列由多个推理请求组成。 图的中心显示了推理请求序列如何随时间批处理到模型实例上,假设每个序列的推理请求以相同的速率到达,序列 A 刚好在 B 之前到达,而序列 A 刚好在 C 之前到达,等等。 最旧策略根据最旧的请求形成一个动态批次,但从不在批次中包含来自给定序列的多个请求(例如,序列 D 中的最后两个推理不会一起批处理)。

合奏模型

集成模型表示一个或多个模型的管道以及这些模型之间输入和输出张量的连接。 集成模型旨在用于封装涉及多个模型的过程,例如“数据预处理 -> 推理 -> 数据后处理”。 为此目的使用集成模型可以避免传输中间张量的开销,并最大限度地减少必须发送给 Triton 的请求数量。

集成调度程序必须用于集成模型,无论集成中的模型使用的调度程序如何。 关于集成调度器,集成模型不是实际模型。 相反,它将集合中模型之间的数据流指定为模型配置中的 ModelEnsembling::Step 条目。 调度器收集每个步骤的输出张量,根据规范将它们作为输入张量提供给其他步骤。 尽管如此,从外部来看,集成模型仍然被视为单个模型。

请注意,集成模型将继承所涉及模型的特征,因此请求标头中的元数据必须符合集成内的模型。 例如,如果其中一个模型是有状态模型,那么集成模型的推理请求应该包含有状态模型中提到的信息,这些信息将由调度程序提供给有状态模型。

例如,考虑一个用于图像分类和分割的集成模型,它具有以下模型配置:

name: "ensemble_model"
platform: "ensemble"
max_batch_size: 1
input [
  {
    name: "IMAGE"
    data_type: TYPE_STRING
    dims: [ 1 ]
  }
]
output [
  {
    name: "CLASSIFICATION"
    data_type: TYPE_FP32
    dims: [ 1000 ]
  },
  {
    name: "SEGMENTATION"
    data_type: TYPE_FP32
    dims: [ 3, 224, 224 ]
  }
]
ensemble_scheduling {
  step [
    {
      model_name: "image_preprocess_model"
      model_version: -1
      input_map {
        key: "RAW_IMAGE"
        value: "IMAGE"
      }
      output_map {
        key: "PREPROCESSED_OUTPUT"
        value: "preprocessed_image"
      }
    },
    {
      model_name: "classification_model"
      model_version: -1
      input_map {
        key: "FORMATTED_IMAGE"
        value: "preprocessed_image"
      }
      output_map {
        key: "CLASSIFICATION_OUTPUT"
        value: "CLASSIFICATION"
      }
    },
    {
      model_name: "segmentation_model"
      model_version: -1
      input_map {
        key: "FORMATTED_IMAGE"
        value: "preprocessed_image"
      }
      output_map {
        key: "SEGMENTATION_OUTPUT"
        value: "SEGMENTATION"
      }
    }
  ]
}

ensemble_scheduling 部分表明将使用集成调度器,集成模型由三个不同的模型组成。 步骤部分中的每个元素指定要使用的模型以及模型的输入和输出如何映射到调度程序识别的张量名称。 例如,step中的第一个元素指定应使用最新版本的image_preprocess_model,其输入“RAW_IMAGE”的内容由“IMAGE”张量提供,其输出“PREPROCESSED_OUTPUT”的内容将映射到“preprocessed_image” ”张量供以后使用。 调度程序识别的张量名称是合奏输入、合奏输出以及 input_map 和 output_map 中的所有值。

构成集成的模型也可能启用了动态批处理。 由于集成模型只是在组合模型之间路由数据,Triton 可以在不修改集成配置的情况下将请求带入集成模型,以利用组合模型的动态批处理。

假设只提供集成模型、预处理模型、分类模型和分割模型,客户端应用程序会将它们视为可以独立处理请求的四个不同模型。 但是,集成调度程序将如下所示查看集成模型。

当收到集成模型的推理请求时,集成调度程序将:

  1. 认识到请求中的“IMAGE”张量映射到预处理模型中的输入“RAW_IMAGE”。

  2. 检查集成中的模型并向预处理模型发送内部请求,因为所需的所有输入张量都已准备就绪。

  3. 识别内部请求的完成,收集输出张量并将内容映射到“preprocessed_image”,这是集成中已知的唯一名称。

  4. 将新收集的张量映射到集合中模型的输入。 在这种情况下,“classification_model”和“segmentation_model”的输入将被映射并标记为就绪。

  5. 检查需要新收集的张量的模型,并将内部请求发送到输入准备就绪的模型,在这种情况下是分类模型和分割模型。 请注意,响应将按任意顺序排列,具体取决于各个模型的负载和计算时间。

  6. 重复步骤 3-5 直到不再发送内部请求,然后使用映射到集成输出名称的张量响应推理请求。

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

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

相关文章

链表--part8--环形链表(leetcode 142)

文章目录 基本思路leetcode 142 环形链表 基本思路 此题为重点题目 此题实际上可以分为俩题: 1 判断是否存在环 2 如果存在返回环的入口 如果不存在返回null 那我就对于这俩种情况进行相关的解释。 判断是否有环 有点类似追及问题,我们可以定义一个快指…

全面理解Starrocks3.0

文章目录 什么是Starrocks适用场景系统架构产品特性 什么是Starrocks StarRocks 是新一代极速全场景 MPP (Massively Parallel Processing) 数据库。StarRocks 的愿景是能够让用户的数据分析变得更加简单和敏捷。用户无需经过复杂的预处理,就可以用 StarRocks 来支…

Python3数据分析与挖掘建模(16)特征降维与特征衍生

1. 特征降维(PCA) 回顾知识点: 特征降维是指将高维特征空间的数据映射到低维空间的过程,以减少特征的数量并保留数据的主要信息。下面是特征降维的一般步骤: (1)求特征协方差矩阵&#xff1a…

I2C协议

i2c硬件电路 i2c总线连接图: 注: i2c的SDA和SCL都需要上拉电阻,改变上拉电阻大小可调节I2C总线的上拉强度,上拉电阻用1k~100k不等,小了驱动能力就强,但电流就大了。不同内核版本上的驱动不一样&#xff…

C语言之指针详解(3)

目录 本章重点 1. 字符指针 2. 数组指针 3. 指针数组 4. 数组传参和指针传参 5. 函数指针 6. 函数指针数组 7. 指向函数指针数组的指针 8. 回调函数 9. 指针和数组面试题的解析、 4. 数组参数、指针参数 我们来看一维数组传参 #include<stdio.h> void test(in…

Rust语言从入门到入坑——(2)Rust在windows上搭建开发环境

文章目录 0 引入1、搭建 Visual Studio Code 开发环境1.1、安装 Rust 编译工具1.2 、VS Code安装 2、官网在线3、总结4、引用 0 引入 开始搭建一个适合在windows上运行的Rust环境。 Rust支持的程序语言很多&#xff1a;可详见官网介绍 1、搭建 Visual Studio Code 开发环境 …

Systrace分析知识点

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、抓取Systrace二、CPU模块知识点三、input 点击事件处理流程四、Vsync 事件处理五、Android 绘制一帧流程分析六、Camx Trace TAG开启方法七、参考文…

管理类联考——英语——趣味篇——刷题需要实现什么目的?

刷题需要实现什么目的&#xff1f;  第一&#xff1a;在真题中巩固考研英语基础 在掌握一定的词汇量和句子分析能力后&#xff0c;开始一字不漏、逐字逐句的完成历年真题的超精读。抄写真题中生词&#xff0c;继续夯实词汇、分析长难句翻译&#xff0c;弄清楚题目中正确选项为…

Science: 功能饮料里面的这种添加剂会使动物寿命更长——这对人类意味着什么尚不清楚...

一项研究表明&#xff0c;当喂食大量牛磺酸&#xff08;一种常见的健康补充剂和能量饮料成分&#xff0c;最早从牛黄中分离出来&#xff09;时&#xff0c;老年小鼠、线虫和猴子可以活得更长或更健康。研究人员证明&#xff0c;这种天然氨基酸的水平与动物的衰老有关&#xff0…

STM32之外设DMA

DMA(Direct Memory Access)—直接存储器存取&#xff0c;是单片机的一个外设&#xff0c;它的主要功能是用来搬数据&#xff0c;但是不需要占用 CPU&#xff0c;即在传输数据的时候&#xff0c;CPU 可以干其他的事情&#xff0c;好像是多线程一样。数据传输支持从外设到存储器或…

Triton教程 -- 模型仓库

Triton教程 – 模型仓库 文章目录 Triton教程 -- 模型仓库存储库布局模型存储库位置本地文件系统 具有环境变量的云存储谷歌云存储S3Azure 存储带凭证文件的云存储&#xff08;测试版&#xff09; 模型版本模型文件TensorRT 模型ONNX 模型TorchScript 模型TensorFlow 模型OpenV…

滴滴实时数据链路建设组件选型实践篇

写在前面 随着滴滴内部技术栈的不断统一&#xff0c;实时相关技术组件资源的不断整合&#xff0c;各业务线实时数据相关开发经验的不断沉淀&#xff0c;基本形成了一套面向公司不同业务场景需求的最佳技术选型和具体落地方案。但同时我们也发现&#xff0c;大部分实时开发同学在…

React基础教程(一):React简介

React基础教程(一)&#xff1a;React简介 1、React是什么&#xff1f; 发生请求获取数据处理数据&#xff08;过滤&#xff0c;整理格式等&#xff09;操作DOM呈现页面 2、谁开发的 由Facebook的软件工程师 Jordan Walke创建于2011年部署于Facebook的newsfeed随后在2012年部…

一本书让你彻底搞懂安卓系统性能优化

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

Transformer详解,中文版架构图

2.2.1 “编码器-解码器”架构 Seq2Seq 思想就是将网络的输入输出分别看作不同的序列&#xff0c;然后实现序列到序列 的映射&#xff0c;其经典实现结构就是“编码器-解码器”框架。编码器-解码器框架如图 2.7 所 示。 图2.7 编码器-解码器的基本框架 在 Seq2Seq 思想应用于自然…

机器鸟实现摆动尾巴功能

1. 功能说明 本文示例将实现R329样机机器鸟摆动尾巴的功能。 2. 电子硬件 在这个示例中&#xff0c;我们采用了以下硬件&#xff0c;请大家参考&#xff1a; 主控板 Basra主控板&#xff08;兼容Arduino Uno&#xff09;‍ 扩展板 Bigfish2.1扩展板‍ 电池7.4V锂电池 电路连接…

新的挑战:WebGL

这段时间一直在死磕 Chromium 的 8K 高清视频播放&#xff0c;虽然之前写过一些关键技术的实现&#xff0c;主要难点差不多攻破&#xff0c;但投入到产品中&#xff0c;依然还要解决很多实际中的问题&#xff0c;比如卡顿、格式支持、音视频不同步等等。前期的相关文章&#xf…

RocketMQ基础API使用以及基本原理探究

文章目录 同步发送异步发送单向发送拉模式随机获取一个queue的消息指定一个queue的消息 顺序消息广播消息延迟消息批量消息过滤消息Tag过滤sql过滤 事务消息RocketMQ常见问题RocketMQ如何保证消息不丢失&#xff1f;RocketMQ的消息持久化机制RocketMQ如何保证消息顺序RocketMQ事…

Day07 Python函数详解

文章目录 第四章 Python函数使用4.1. 函数介绍4.2. 函数的定义与使用4.2.1. 函数的定义4.2.2. 调用 4.3. 函数的参数4.4. 函数的返回值4.4.1. 返回值介绍4.4.2. None类型 4.5. 函数说明4.5.1. 函数注释4.5.2. 函数的4中定义方式4.5.3. 函数的调用 4.6. 函数的嵌套调用4.7. 函数…

哪款 IMG BXS GPU 适合您的汽车?

Imagination 是汽车行业领先的图形处理器供应商。Imagination 的 GPU IP 经过了九代更新迭代&#xff0c;为车辆提供了舒适性和安全性&#xff0c;在汽车行业的总出货量接近 5 亿。通过将响应迅速的 HMI&#xff08;人机界面&#xff09;与功能日益强大的高级驾驶员辅助系统相结…