NVIDIA Morpheus (24.10.01)

使用 Forest Inference Library (FIL) 的异常行为分析示例

此示例说明了如何使用 Morpheus 通过利用 Forest Inference Library (FIL) 模型和 Triton 推理服务器自动检测 NVIDIA SMI 日志中的异常行为。我们将要搜索的特定行为是加密货币挖矿。

环境

是否支持

注释

Conda

Morpheus Docker 容器 需要在主机上启动 Triton
Morpheus 发布容器 需要在主机上启动 Triton
开发容器 需要使用 dev-triton-start 脚本,并将 --server_url=localhost:8000 替换为 --server_url=triton:8000

此示例的目标是识别受监控的 NVIDIA GPU 是否正在积极挖矿加密货币,并在检测到时采取纠正措施。加密货币挖矿可能会大量消耗 GPU 集群的资源,并且检测挖矿可能很困难,因为挖矿工作负载看起来与其他有效工作负载相似。

在此示例中,我们将使用 Morpheus 提供的 ABP NVSMI 检测模型。此模型能够从 nvidia-smi 日志的输出中检测加密货币挖矿的特征。对于 nvidia-smi 日志数据可用的每个时间戳,模型将输出一个概率,指示是否检测到挖矿。

数据集

此工作流程旨在处理的数据集包含定期时间间隔的 NVIDIA GPU 指标,并由 NetQ 代理提取并序列化为 JSON。数据集中的每一行都包含与 nvidia-smi 实用程序返回的大部分相同的信息。我们不会直接检查完整的消息,因为每一行包含 176 个不同的列,但可以使用 nvidia-smi dmon 命令了解数据集是如何生成的。如果您自己运行此命令,输出将类似于以下内容

复制
已复制!
            

$ nvidia-smi dmon # gpu pwr gtemp mtemp sm mem enc dec mclk pclk # Idx W C C % % % % MHz MHz 0 70 48 - 5 1 0 0 7000 1350 0 68 48 - 11 1 0 0 7000 1350 0 69 48 - 3 1 0 0 7000 1350 0 270 53 - 10 1 0 0 7000 1875 0 274 55 - 75 46 0 0 7000 1740 0 278 55 - 86 56 0 0 7000 1755 0 279 56 - 99 63 0 0 7000 1755 0 277 57 - 86 55 0 0 7000 1755 0 281 57 - 85 54 0 0 7000 1740

输出中的每一行代表在单个时间点的 GPU 指标。随着工具的进行,GPU 开始被利用,并且 SM% 和 Mem% 值随着内存加载到 GPU 和执行计算而增加。我们将要使用的模型可以摄取此信息,并确定 GPU 是否正在挖矿加密货币,而无需来自主机机器的额外信息。

在此示例中,我们将使用 examples/data/nvsmi.jsonlines 数据集,该数据集已知包含挖矿行为配置文件。该数据集为 .jsonlines 格式,这意味着每一新行代表一个新的 JSON 对象。为了解析此数据,必须先摄取数据,按行拆分为单独的 JSON 对象,然后解析为 cuDF DataFrame。这些都将由 Morpheus 处理。

生成您自己的数据集

此示例可以轻松应用于从您自己的 NVIDIA GPU 设备生成的数据集。如果您的环境中未部署 NetQ,则提供了 nvsmi_data_extract.py 脚本,该脚本使用 pyNVMLpandas 来生成类似于 NetQ 的数据。pyNVML 包含 NVIDIA Management Library (NVML) 的 Python 绑定,NVML 与 nvidia-smi 使用的库相同。

默认情况下未安装 pyNVML,请使用以下命令安装它

复制
已复制!
            

conda env update --solver=libmamba -n morpheus --file conda/environments/examples_cuda-125_arch-x86_64.yaml

运行以下命令开始生成您的数据集

复制
已复制!
            

python nvsmi_data_extract.py

这将每秒向名为 nvsmi.jsonlines 的输出文件写入一个新条目,直到您按下 Ctrl+C 退出。

在此示例中,我们将使用的流水线是一个简单的前馈线性流水线,其中来自每个阶段的数据流向下一个阶段。像此示例一样,没有自定义阶段的简单线性流水线可以通过 Morpheus CLI 或使用 Python 库进行配置。在此示例中,我们将使用 Morpheus CLI。

以下是流水线的可视化,显示了所有阶段和数据类型,以及数据从一个阶段流向下一个阶段的过程。

pipeline.png

此示例利用 Triton 推理服务器执行推理。

启动 Triton

拉取 Triton 的 Docker 镜像

复制
已复制!
            

docker pull nvcr.io/nvidia/morpheus/morpheus-tritonserver-models:24.10

运行以下命令以启动 Triton 并加载 abp-nvsmi-xgb XGBoost 模型

复制
已复制!
            

docker run --rm -ti --gpus=all -p8000:8000 -p8001:8001 -p8002:8002 nvcr.io/nvidia/morpheus/morpheus-tritonserver-models:24.10 tritonserver --model-repository=/models/triton-model-repo --exit-on-error=false --model-control-mode=explicit --load-model abp-nvsmi-xgb

这将启动 Triton 并且仅加载 abp-nvsmi-xgb 模型。此模型已配置最大批处理大小为 32768,并使用动态批处理以提高性能。

一旦 Triton 加载了模型,将显示以下内容

复制
已复制!
            

+-------------------+---------+--------+ | Model | Version | Status | +-------------------+---------+--------+ | abp-nvsmi-xgb | 1 | READY | +-------------------+---------+--------+

注意:如果输出中没有此内容,请检查 Triton 日志中是否有与加载模型相关的任何错误消息。

使用 Morpheus CLI,可以配置和运行整个流水线,而无需编写任何代码。使用 morpheus run pipeline-fil 命令,我们可以通过在命令行上指定每个阶段的名称和配置来构建流水线。每个阶段的输出将成为下一个阶段的输入。

以下命令行是构建和启动流水线的完整命令。每一新行代表一个新的阶段。每个阶段上方的注释提供了有关为什么添加和配置该阶段的信息(您可以复制/粘贴带有注释的完整命令)。

从 Morpheus 仓库根目录运行

复制
已复制!
            

# Launch Morpheus printing debug messages morpheus --log_level=DEBUG \ `# Run a pipeline with 8 threads and a model batch size of 1024 (Must be equal or less than Triton config)` \ run --num_threads=8 --pipeline_batch_size=1024 --model_max_batch_size=1024 \ `# Specify a NLP pipeline with 256 sequence length (Must match Triton config)` \ pipeline-fil --columns_file=data/columns_fil.txt \ `# 1st Stage: Read from file` \ from-file --filename=examples/data/nvsmi.jsonlines \ `# 2nd Stage: Deserialize batch DataFrame into ControlMessages` \ deserialize \ `# 3rd Stage: Preprocessing converts the input data into BERT tokens` \ preprocess \ `# 4th Stage: Send messages to Triton for inference. Specify the model loaded in Setup` \ inf-triton --model_name=abp-nvsmi-xgb --server_url=localhost:8000 \ `# 5th Stage: Monitor stage prints throughput information to the console` \ monitor --description "Inference Rate" --smoothing=0.001 --unit inf \ `# 6th Stage: Add results from inference to the messages` \ add-class \ `# 7th Stage: Convert from objects back into strings. Ignore verbose input data` \ serialize --include 'mining' \ `# 8th Stage: Write out the JSON lines to the detections.jsonlines file` \ to-file --filename=detections.jsonlines --overwrite

如果成功,应显示以下内容

复制
已复制!
            

Configuring Pipeline via CLI Loaded columns. Current columns: [['nvidia_smi_log.gpu.fb_memory_usage.used', 'nvidia_smi_log.gpu.fb_memory_usage.free', 'nvidia_smi_log.gpu.utilization.gpu_util', 'nvidia_smi_log.gpu.utilization.memory_util', 'nvidia_smi_log.gpu.temperature.gpu_temp', 'nvidia_smi_log.gpu.temperature.gpu_temp_max_threshold', 'nvidia_smi_log.gpu.temperature.gpu_temp_slow_threshold', 'nvidia_smi_log.gpu.power_readings.power_draw', 'nvidia_smi_log.gpu.clocks.graphics_clock', 'nvidia_smi_log.gpu.clocks.sm_clock', 'nvidia_smi_log.gpu.clocks.mem_clock', 'nvidia_smi_log.gpu.applications_clocks.graphics_clock', 'nvidia_smi_log.gpu.applications_clocks.mem_clock', 'nvidia_smi_log.gpu.default_applications_clocks.graphics_clock', 'nvidia_smi_log.gpu.default_applications_clocks.mem_clock', 'nvidia_smi_log.gpu.max_clocks.graphics_clock', 'nvidia_smi_log.gpu.max_clocks.sm_clock', 'nvidia_smi_log.gpu.max_clocks.mem_clock']] Starting pipeline via CLI... Ctrl+C to Quit Config: { "ae": null, "class_labels": [ "mining" ], "debug": false, "edge_buffer_size": 128, "feature_length": 18, "fil": { "feature_columns": [ "nvidia_smi_log.gpu.pci.tx_util", "nvidia_smi_log.gpu.pci.rx_util", "nvidia_smi_log.gpu.fb_memory_usage.used", "nvidia_smi_log.gpu.fb_memory_usage.free", "nvidia_smi_log.gpu.bar1_memory_usage.total", "nvidia_smi_log.gpu.bar1_memory_usage.used", "nvidia_smi_log.gpu.bar1_memory_usage.free", "nvidia_smi_log.gpu.utilization.gpu_util", "nvidia_smi_log.gpu.utilization.memory_util", "nvidia_smi_log.gpu.temperature.gpu_temp", "nvidia_smi_log.gpu.temperature.gpu_temp_max_threshold", "nvidia_smi_log.gpu.temperature.gpu_temp_slow_threshold", "nvidia_smi_log.gpu.temperature.gpu_temp_max_gpu_threshold", "nvidia_smi_log.gpu.temperature.memory_temp", "nvidia_smi_log.gpu.temperature.gpu_temp_max_mem_threshold", "nvidia_smi_log.gpu.power_readings.power_draw", "nvidia_smi_log.gpu.clocks.graphics_clock", "nvidia_smi_log.gpu.clocks.sm_clock", "nvidia_smi_log.gpu.clocks.mem_clock", "nvidia_smi_log.gpu.clocks.video_clock", "nvidia_smi_log.gpu.applications_clocks.graphics_clock", "nvidia_smi_log.gpu.applications_clocks.mem_clock", "nvidia_smi_log.gpu.default_applications_clocks.graphics_clock", "nvidia_smi_log.gpu.default_applications_clocks.mem_clock", "nvidia_smi_log.gpu.max_clocks.graphics_clock", "nvidia_smi_log.gpu.max_clocks.sm_clock", "nvidia_smi_log.gpu.max_clocks.mem_clock", "nvidia_smi_log.gpu.max_clocks.video_clock", "nvidia_smi_log.gpu.max_customer_boost_clocks.graphics_clock" ] }, "log_config_file": null, "log_level": 10, "mode": "FIL", "model_max_batch_size": 1024, "num_threads": 8, "pipeline_batch_size": 1024 } CPP Enabled: True ====Registering Pipeline==== ====Registering Pipeline Complete!==== ====Starting Pipeline==== ====Pipeline Started==== ====Building Pipeline==== Added source: <from-file-0; FileSourceStage(filename=examples/data/nvsmi.jsonlines, iterative=False, file_type=FileTypes.Auto, repeat=1, filter_null=True)> └─> morpheus.MessageMeta Added stage: <deserialize-1; DeserializeStage()> └─ morpheus.MessageMeta -> morpheus.ControlMessage Added stage: <preprocess-fil-2; PreprocessFILStage()> └─ morpheus.ControlMessage -> morpheus.ControlMessage Added stage: <inference-3; TritonInferenceStage(model_name=abp-nvsmi-xgb, server_url=localhost:8000, force_convert_inputs=False, use_shared_memory=False)> └─ morpheus.ControlMessage -> morpheus.ControlMessage Added stage: <monitor-4; MonitorStage(description=Inference Rate, smoothing=0.001, unit=inf, delayed_start=False, determine_count_fn=None)> └─ morpheus.ControlMessage -> morpheus.ControlMessage Added stage: <add-class-5; AddClassificationsStage(threshold=0.5, labels=[], prefix=)> └─ morpheus.ControlMessage -> morpheus.ControlMessage Added stage: <serialize-6; SerializeStage(include=['mining'], exclude=['^ID$', '^_ts_'], fixed_columns=True)> └─ morpheus.ControlMessage -> morpheus.MessageMeta Added stage: <to-file-7; WriteToFileStage(filename=detections.jsonlines, overwrite=True, file_type=FileTypes.Auto)> └─ morpheus.MessageMeta -> morpheus.MessageMeta ====Building Pipeline Complete!==== Starting! Time: 1656353254.9919598 Inference Rate[Complete]: 1242inf [00:00, 1863.04inf/s] ====Pipeline Complete====

输出文件 detections.jsonlines 将为每个输入行包含一个布尔值。在某个时候,这些值将从 0 切换到 1

复制
已复制!
            

... {"mining": 0} {"mining": 0} {"mining": 0} {"mining": 0} {"mining": 1} {"mining": 1} {"mining": 1} {"mining": 1} {"mining": 1} {"mining": 1} {"mining": 1} {"mining": 1} ...

我们已剥离输入数据以使检测更容易识别。省略参数 --include 'mining' 将在检测文件中显示输入数据。

上一步 示例
下一步 使用 Morpheus 的 ABP 检测示例
© 版权所有 2024, NVIDIA。 上次更新于 2024 年 12 月 3 日。