Linux Kernel Dirty Page Writeback 与 IO 拥塞联调深度实战

Linux Kernel Dirty Page Writeback 与 IO 拥塞联调深度实战:AI 训练集群稳定性工程

引言:一个被忽视的训练稳定性杀手

在大规模 AI 集群中,工程师往往会将精力集中在 GPU 算力利用率、通信带宽和模型收敛速度上,却容易忽略一个底层问题:Page Cache Dirty Page 突然集中回写引发的 IO 拥塞,会导致 GPU 训练出现间歇性"卡死"(GPU starvation)。这种现象表现为训练 throughput 周期性骤降,PyTorch dataloader 出现莫名其妙的等待,NCCL 通信超时,甚至导致大规模训练任务崩溃。

本文从 Linux 内核内存管理与 block layer 子系统出发,深度分析 dirty page 回写的完整生命周期、IO 拥塞的形成机制,并提供一套工程化的诊断与调优方法论。我们将结合 bpftrace 动态追踪、cgroup v2 memory/IO 控制器、BPF-LSM 拦截技术,来构建一个完整的"脏页风暴"防御体系。

一、Linux Page Cache 与 Dirty Page 机制深度剖析

1.1 Page Cache 的核心数据结构

Linux 内核通过 struct page 和 struct folio(自 5.16 引入)来管理页缓存。当一个文件被读取或写入时,其内存页面会被加入 Page Cache,由 address_space 结构组织起来:


struct address_space {
    struct inode        *host;           // 关联的 inode
    struct xarray       i_pages;         // 页面索引树(XArray)
    unsigned long       nrpages;         // 总页数
    const struct address_space_operations *aops;
    gfp_t               gfp_mask;
};

// Folio — 多页缓存单元(Linux 5.16+)
struct folio {
    unsigned long   flags;       // PG_dirty, PG_writeback 等标志
    struct list_head lru;        // LRU 链表节点
    struct address_space *mapping;
    void    *private;            // 文件系统私有数据
    // 复合页的物理页信息...
};

当用户空间进程对文件进行 write() 系统调用时,Page Cache 的处理流程为:

  1. write() → vfs_write() → 文件对应的 write_iter() 方法
  2. 调用 generic_perform_write() → a_ops->write_begin() 锁定页面
  3. 通过 copy_from_user() 将用户数据拷入 Page Cache
  4. 设置 PG_dirty 标志位,标记页面为脏页
  5. 数据此时在内存中,但尚未落盘
  6. 1.2 Dirty Page 状态机

    
    Clean Page ──write()──▶ Dirty Page
        ▲                      │
        │                      │ writeback 线程开始刷盘
        │                      ▼
        │              Writeback Page (PG_writeback)
        │                      │
        │                      │ IO 完成
        │                      ▼
        └───── page_cleaned ── Clean Page
    

    关键的状态转换标志:

    • PG_dirty(bit 4):表示内容已修改,与磁盘不同步
    • PG_writeback(bit 5):表示正在进行 IO 回写
    • PG_reclaim(bit 6):表示正在被内存回收扫描

    1.3 Writeback 控制参数

    内核通过 /proc/sys/vm/ 目录下的参数控制 writeback 行为,AI 训练场景中需要重点关注:

    
    # 脏页占总内存的百分比阈值,超过后进程 write() 阻塞开始刷盘
    cat /proc/sys/vm/dirty_ratio          # 默认 20(20%)
    cat /proc/sys/vm/dirty_background_ratio  # 默认 10(10%)
    
    # 基于字节数的精确控制(CentOS 8+ / Ubuntu 22.04+ 默认)
    cat /proc/sys/vm/dirty_bytes          # 绝对字节数
    cat /proc/sys/vm/dirty_background_bytes
    
    # 脏页过期时间(单位:百分之一秒)
    cat /proc/sys/vm/dirty_expire_centisecs  # 默认 3000(30秒)
    cat /proc/sys/vm/dirty_writeback_centisecs  # 默认 500(5秒)
    
    # 内存回收相关
    cat /proc/sys/vm/swappiness           # 默认 60
    cat /proc/sys/vm/vfs_cache_pressure   # 默认 100
    

    二、Dirty Page 回写路径的完整内核追踪

    2.1 Writeback 内核线程

    每个 bdi(Backing Device Information)设备都有一个 wb_workform 工作队列和一个 bdi_writeback 结构:

    
    // include/linux/backing-dev.h
    struct backing_dev_info {
        struct list_head bdi_list;
        unsigned long ra_pages;           // 预读窗口
        unsigned long io_pages;           // IO 页数
        struct bdi_writeback *wb;         // writeback 单元
        struct list_head wb_list;
        unsigned long avg_write_bandwidth;
        unsigned long min_bandwidth;
        unsigned long max_bandwidth;
        // ...
    };
    
    struct bdi_write_back {
        struct backing_dev_info *bdi;
        unsigned long state;
        unsigned long last_old_flush;
        struct list_head b_dirty;         // 脏页 inode 链表
        struct list_head b_io;            // 等待回写的 inode
        struct list_head b_more_io;       // 需要更多回写的
        struct wb_writeback_work *work;
        unsigned long dirty_ratelimit;    // 当前回写速率
        // ...
    };
    

    Writeback 触发三条路径:

    1. 后台阈值触发:当脏页比例超过 dirty_background_ratio,wb_workfn() 开始异步回写
    2. 脏页过期触发:超过 dirty_expire_centisecs 的脏页会被周期性回写
    3. 显式阻塞触发:当脏页超过 dirty_ratio,write() 调用者会被强制阻塞(dirty throttle)
    4. 2.2 Dirty Page Rate Limiting — 内核流控器

      内核使用 dirty_throttle_control 结构中的令牌桶算法来控制回写速率,避免 IO 拥塞:

      
      // mm/page-writeback.c
      static void balance_dirty_pages(struct bdi_writeback *wb)
      {
          struct dirty_throttle_control *dtc = wb->dtc;
          unsigned long dirty = global_node_page_state(NR_FILE_DIRTY);
          unsigned long thresh = global_dirty_limit();
          unsigned long bw = wb->avg_write_bandwidth;
          
          // 计算目标回写带宽
          pause = HZ * written / (bw + 1);
          pause = min(pause, HZ / 10);   // 最长 100ms
          pause = max(pause, 1);          // 最短 1ms
          
          __set_current_state(TASK_KILLABLE);
          io_schedule_timeout(pause);
      }
      

      当 AI 训练进程持续写入 checkpoint、日志或数据预处理结果时,dirty page 累积速度可能远超过磁盘带宽,此时内核会强制 throttle 写入进程。如果该进程正好持有 dataloader 的锁或网络通信的缓冲区,就会导致整个训练流水线停顿。

      2.3 io_schedule_timeout 的连锁反应

      当 write() 调用被 balance_dirty_pages() 阻塞后,其影响链路为:

      
      训练写线程 → write() 阻塞 → dataloader buffer 满
          ↓
      GPU 数据供给中断 → GPU utilization 跌落
          ↓
      NCCL AllReduce 等待 → 通信超时检测触发
          ↓
      训练框架 watchdog 超时 → 触发 checkpoint 保存 → 更多脏页
          ↓
      恶性循环
      

      三、IO 拥塞诊断方法论

      3.1 使用 bpftrace 追踪 Dirty Page 生命周期

      下面的 bpftrace 脚本跟踪 dirty page 的产生、回写和清空全过程:

      
      #!/usr/bin/bpftrace
      
      // 追踪脏页标记(set_page_dirty)
      kprobe:set_page_dirty {
          $page = (struct page *)arg0;
          $mapping = $page->mapping;
          $inode = $mapping->host;
          
          printf("DIRTY: pid=%d comm=%s ino=%lu size=%lu offset=%lu\n",
                 pid, comm, $inode->i_ino, 
                 $inode->i_size, $page->index);
      }
      
      // 追踪 writeback 开始
      kprobe:wb_workfn {
          printf("WB_START: time=%llu\n", nsecs);
      }
      
      // 追踪 balance_dirty_pages 阻塞
      kprobe:balance_dirty_pages {
          printf("THROTTLE: pid=%d comm=%s at_time=%llu\n",
                 pid, comm, nsecs);
      }
      
      // 追踪 IO 完成
      kprobe:end_page_writeback {
          @completed++;
          printf("WB_COMPLETE: total=%llu\n", @completed);
      }
      
      interval:s:5 {
          print(@dirty_counts);
      }
      

      执行诊断命令:

      
      sudo bpftrace dirty_trace.bt -o dirty_trace.log &
      # 训练启动后 10 分钟
      cat /proc/vmstat | grep -E "dirty|writeback|nr_"
      

      3.2 使用 /proc/vmstat 实时监控

      
      # 监控脏页和回写统计
      watch -n 1 'grep -E "dirty|writeback|nr_" /proc/vmstat'
      

      关键指标说明:

      指标 含义 异常阈值
      nr_dirty 当前脏页数量 持续 > dirty_ratio 阈值 50%
      nr_writeback 正在回写的页数 持续 > 1000
      nr_dirty_background_thresh 后台回写触发次数 频繁触发
      pgpgin / pgpgout 页面换入/换出计数 非预期时异常
      pswpin / pswpout 交换分区读写 非零即为异常

      3.3 使用 blktrace + blkparse 分析 IO 模式

      
      # 捕获块设备 IO 模式
      sudo blktrace -d /dev/nvme0n1 -o trace &
      # 运行训练任务...
      
      # 解析并统计 IO 延迟分布
      blkparse -i trace -d trace.bin
      btt -i trace.bin -l trace.latencies
      # 输出:IO 提交的延迟分布、完成的延迟分布、Q2C(队列到完成)时间
      

      典型的"脏页风暴"IO 模式特征:

      • IO 队列深度突然飙升(从几十到几千)
      • 顺序写入被拆碎为大量随机小页写入(4KB)
      • IO 平均延迟从 50μs 飙升至 50ms+
      • SSD 的 P99 延迟突破 1s

      四、AI 训练场景工程化解决方案

      4.1 方案一:Dirty Page 预防 — 内存分配策略

      核心思路:在训练启动前,提前分配并预热 Page Cache,避免 checkpoint 写入时临时产生大量脏页。

      
      # preallocate_fscache.py
      import os
      import mmap
      
      def preallocate_pagecache(filepath, size_gb):
          """预分配 page cache 空间,减少脏页突发"""
          size = size_gb * 1024 * 1024 * 1024
          
          with open(filepath, 'w+b') as f:
              # fallocate 预分配文件(不产生脏页)
              os.posix_fallocate(f.fileno(), 0, size)
              
              # 建议内核该文件会被顺序访问
              os.posix_fadvise(f.fileno(), 0, size, 
                              os.POSIX_FADV_SEQUENTIAL)
              
              # 对 mmap 区域进行 madvise
              mm = mmap.mmap(f.fileno(), size)
              # MADV_HUGEPAGE - 建议内核使用大页
              mm.madvise(mmap.MADV_HUGEPAGE)
              mm.close()
      
      if __name__ == "__main__":
          preallocate_pagecache("/data/checkpoints/next.ckpt", 10)
      

      4.2 方案二:Dirty Page 速率控制 — 动态调节阈值

      核心思路:训练运行时动态降低 dirty_ratio,提前开始回写,避免脏页积压导致的突发风暴。

      
      # vm_dirty_tuner.py — 动态调节 vm.dirty 参数
      import time
      import os
      import signal
      
      class DirtyPageTuner:
          """
          AI 训练场景下的 Dirty Page 自动调优器
          """
          
          # 模式配置
          PROFILES = {
              "normal": {
                  "dirty_ratio": 20,
                  "dirty_background_ratio": 10,
                  "dirty_expire_centisecs": 3000,
                  "dirty_writeback_centisecs": 500,
                  "swappiness": 10,
              },
              "checkpoint_writing": {
                  # checkpoint 写入前降低阈值,提前开始回写
                  "dirty_ratio": 5,
                  "dirty_background_ratio": 2,
                  "dirty_expire_centisecs": 1000,
                  "dirty_writeback_centisecs": 200,
                  "swappiness": 0,
              },
              "recovery": {
                  # 训练完成后恢复默认
                  "dirty_ratio": 30,
                  "dirty_background_ratio": 15,
                  "dirty_expire_centisecs": 5000,
                  "dirty_writeback_centisecs": 1000,
                  "swappiness": 10,
              }
          }
          
          def __init__(self):
              self.original = {}
              self._save_defaults()
          
          def _write_proc(self, path, value):
              with open(f"/proc/sys/vm/{path}", 'w') as f:
                  f.write(str(value))
          
          def _read_proc(self, path):
              with open(f"/proc/sys/vm/{path}", 'r') as f:
                  return f.read().strip()
          
          def _save_defaults(self):
              keys = ["dirty_ratio", "dirty_background_ratio", 
                      "dirty_expire_centisecs", "dirty_writeback_centisecs",
                      "swappiness"]
              for k in keys:
                  self.original[k] = self._read_proc(k)
          
          def apply_profile(self, profile_name):
              profile = self.PROFILES[profile_name]
              for key, value in profile.items():
                  self._write_proc(key, value)
                  print(f"[TUNER] Set {key} = {value}")
          
          def get_stats(self):
              """获取当前脏页统计"""
              stats = {}
              with open('/proc/vmstat', 'r') as f:
                  for line in f:
                      parts = line.split()
                      if parts[0] in ('nr_dirty', 'nr_writeback', 
                                    'nr_unstable', 'nr_dirtied',
                                    'nr_written', 'nr_dirty_threshold',
                                    'nr_dirty_background_threshold'):
                          stats[parts[0]] = int(parts[1])
              return stats
          
          def monitor_loop(self, interval=2.0):
              """持续监控并报警"""
              while True:
                  stats = self.get_stats()
                  dirty = stats.get('nr_dirty', 0)
                  thresh = stats.get('nr_dirty_threshold', 1)
                  ratio = dirty / thresh * 100 if thresh else 0
                  
                  if ratio > 80:
                      print(f"[ALERT] Dirty pages at {ratio:.1f}% "
                            f"of threshold! ({dirty}/{thresh})")
                      self.apply_profile("checkpoint_writing")
                  elif ratio < 30:
                      print(f"[INFO] Dirty pages safe: {ratio:.1f}%")
                  
                  time.sleep(interval)
      
      # 集成到训练启动脚本
      if __name__ == "__main__":
          tuner = DirtyPageTuner()
          
          # 训练开始前:降低阈值预回写
          tuner.apply_profile("checkpoint_writing")
          
          import subprocess
          proc = subprocess.Popen([
              "python", "train.py",
              "--config", "config.yaml"
          ])
          
          try:
              proc.wait()
          finally:
              # 训练完成后恢复
              tuner.apply_profile("recovery")
      

      4.3 方案三:IO 拥塞避免 — BPF-LSM 脏页拦截

      利用 BPF-LSM 技术在内核 file_receive 等挂载点注入策略,实现更细粒度的控制:

      
      // dirty_limit.bpf.c — BPF-LSM 程序拦截大脏页产生行为
      #include "vmlinux.h"
      #include <bpf/bpf_helpers.h>
      #include <bpf/bpf_tracing.h>
      
      #define MAX_DIRTY_PAGES_PER_SEC 500000  // 每秒最大脏页数
      #define THRESHOLD_ACTION 1
      
      struct {
          __uint(type, BPF_MAP_TYPE_HASH);
          __uint(max_entries, 1024);
          __type(key, u32);    // pid
          __type(value, u64);  // 脏页计数
      } dirty_page_counter SEC(".maps");
      
      struct {
          __uint(type, BPF_MAP_TYPE_ARRAY);
          __uint(max_entries, 1);
          __type(key, u32);
          __type(value, u64);  // 全局计数
      } global_dirty_count SEC(".maps");
      
      // 挂载点:写操作标记脏页时
      SEC("lsm/set_page_dirty")
      int BPF_PROG(limit_dirty_pages, struct page *page)
      {
          u32 pid = bpf_get_current_pid_tgid() >> 32;
          u64 *count, global = 0;
          u64 key = 0;
          
          // 更新 per-pid 计数
          count = bpf_map_lookup_elem(&dirty_page_counter, &pid);
          if (count) {
              __sync_fetch_and_add(count, 1);
          } else {
              u64 init = 1;
              bpf_map_update_elem(&dirty_page_counter, &pid, &init, BPF_ANY);
          }
          
          // 检查全局计数
          u64 *gcount = bpf_map_lookup_elem(&global_dirty_count, &key);
          if (gcount && *gcount > MAX_DIRTY_PAGES_PER_SEC) {
              // 超过限制,返回 -EAGAIN 让应用自行退避
              bpf_printk("DIRTY LIMIT: pid=%d throttle!\n", pid);
              return -EAGAIN;
          }
          
          if (gcount)
              __sync_fetch_and_add(gcount, 1);
          
          return 0;
      }
      
      struct timer_ctx {
          u32 unused;
      };
      
      // 定时器:每秒重置计数器(通过 BPF timer)
      struct {
          __uint(type, BPF_MAP_TYPE_ARRAY);
          __uint(max_entries, 1);
          __type(key, u32);
          __type(value, struct bpf_timer);
      } timer_map SEC(".maps");
      
      SEC("tp_btf/sched_process_fork")
      int reset_dirty_counter()
      {
          u32 key = 0;
          u64 zero = 0;
          bpf_map_update_elem(&global_dirty_count, &key, &zero, BPF_ANY);
          return 0;
      }
      
      char LICENSE[] SEC("license") = "GPL";
      

      对应的加载和控制程序:

      
      # dirty_limit_loader.py
      from bcc import BPF
      import time
      import ctypes
      
      bpf_text = r"""
      // 上述 BPF 代码...
      """
      
      class DirtyPageLimiter:
          def __init__(self):
              self.bpf = BPF(text=bpf_text)
              print("[BPF-LSM] 程序已加载")
          
          def set_limit(self, max_pages_per_sec):
              """设置每秒最大脏页数"""
              limit_map = self.bpf.get_table("max_dirty_limit")
              key = ctypes.c_uint(0)
              val = ctypes.c_ulong(max_pages_per_sec)
              limit_map[key] = val
              print(f"[BPF-LSM] 脏页限制设置为 {max_pages_per_sec} pages/sec")
          
          def get_stats(self):
              """获取各进程的脏页产生速率"""
              counter = self.bpf.get_table("dirty_page_counter")
              results = {}
              for key, value in counter.items():
                  pid = key.value
                  count = value.value
                  results[pid] = count
              return results
          
          def monitor(self):
              """实时监控"""
              while True:
                  time.sleep(5)
                  stats = self.get_stats()
                  total = sum(stats.values())
                  print(f"[MONITOR] Total dirty pages/sec: {total}")
                  
                  if total > 500000:
                      self.set_limit(300000)
                      print("[MONITOR] Reducing limit to 300000")
      
      if __name__ == "__main__":
          limiter = DirtyPageLimiter()
          limiter.monitor()
      

      4.4 方案四:cgroup v2 I/O Weight 隔离

      使用 cgroup v2 的 IO 控制器来隔离 checkpoint 写入的磁盘带宽,保证数据读取的 IO 优先级:

      
      # 训练数据读取组:高 IO 权重
      mkdir /sys/fs/cgroup/training_data
      echo "800" > /sys/fs/cgroup/training_data/io.weight
      echo "8:0 rbps=2147483647 wbps=2147483647 riops=2147483647 wiops=2147483647" \
          > /sys/fs/cgroup/training_data/io.max
      
      # checkpoint 写入组:受控权重
      mkdir /sys/fs/cgroup/checkpoint_io
      echo "100" > /sys/fs/cgroup/checkpoint_io/io.weight
      
      # 限制 checkpoint 不能占用超过 2GB/s 写入带宽
      echo "8:0 wbps=2147483648" > /sys/fs/cgroup/checkpoint_io/io.max
      
      # 将进程绑定到对应 cgroup
      echo $DATALOADER_PID > /sys/fs/cgroup/training_data/cgroup.procs
      echo $CKPT_WRITER_PID > /sys/fs/cgroup/checkpoint_io/cgroup.procs
      

      4.5 方案五:用户空间 Page Cache 旁路

      对于 AI 训练中的 checkpoint 写入,可以绕过 Page Cache,使用 O_DIRECT 直接 IO:

      
      // direct_write_checkpoint.c
      #include <fcntl.h>
      #include <unistd.h>
      #include <stdlib.h>
      #include <stdio.h>
      #include <string.h>
      
      #define BUFFER_SIZE (4 * 1024 * 1024)  // 4MB 对齐缓冲区
      
      int write_checkpoint_direct(const char *path, void *data, size_t len)
      {
          // O_DIRECT 绕过 Page Cache,避免产生脏页
          int fd = open(path, O_WRONLY | O_CREAT | O_DIRECT | O_TRUNC, 0644);
          if (fd < 0) {
              perror("open O_DIRECT failed");
              return -1;
          }
          
          // O_DIRECT 要求内存对齐(对齐到块设备逻辑块大小,通常 512B 或 4KB)
          void *buf;
          if (posix_memalign(&buf, 4096, BUFFER_SIZE) != 0) {
              perror("posix_memalign");
              close(fd);
              return -1;
          }
          
          size_t remaining = len;
          char *src = (char *)data;
          
          while (remaining > 0) {
              size_t chunk = (remaining > BUFFER_SIZE) ? BUFFER_SIZE : remaining;
              
              memcpy(buf, src, chunk);
              
              // 确保写入大小是块大小的倍数
              size_t aligned_chunk = ((chunk + 511) / 512) * 512;
              
              ssize_t written = write(fd, buf, aligned_chunk);
              if (written < 0) {
                  perror("write failed");
                  break;
              }
              
              src += chunk;
              remaining -= chunk;
          }
          
          // 确保数据完全落盘
          fdatasync(fd);
          close(fd);
          free(buf);
          
          return 0;
      }
      

      五、生产环境综合案例

      5.1 问题场景

      某 AI 集群(A100 × 8 × 16 节点)训练 175B 模型,每个 GPU 每 30 分钟保存一次 checkpoint(每个 checkpoint ~2.8GB)。当 128 个 GPU 同时开始保存 checkpoint 时,数据预处理节点的 Page Cache 在 10 秒内积累约 360GB 脏页,触发 writeback 风暴。

      5.2 症状数据

      指标 正常值 风暴期间(无调优)
      GPU Utilization 95%+ 42%
      NCCL AllReduce 时间 12ms 850ms
      NVMe 写入带宽 2.1GB/s 6.8GB/s(无序突发)
      IO P99 延迟 85μs 12000μs(12ms)
      训练 throughput 156 samples/s 41 samples/s

      5.3 调优措施与效果

      第一阶段:降低 dirty_page 阈值

      
      echo 5 > /proc/sys/vm/dirty_ratio
      echo 2 > /proc/sys/vm/dirty_background_ratio
      echo 1500 > /proc/sys/vm/dirty_expire_centisecs
      

      效果:回写提前发生,风暴峰值降低 60%。但仍有约 20% 的 throughput 损失。

      第二阶段:checkpoint O_DIRECT + 时间错位

      
      # 各 GPU 错开 checkpoint 时间(错开 30 秒)
      ckpt_time = base_time + gpu_rank * 30
      save_checkpoint(path, use_direct_io=True)
      

      效果:风暴基本消失,throughput 恢复至 92%。

      第三阶段:cgroup v2 IO 隔离 + BPF-LSM 兜底

      实施完整的 IO 隔离方案后,最终效果:

      指标 调优前 调优后
      GPU Utilization 42% 96%
      Checkpoint 时间 一次性 30s 分散 30×1s
      训练 throughput 41 samples/s 152 samples/s
      IO P99 延迟 12ms 120μs

      5.4 持续监控 Dashboard

      建议部署的 Prometheus 监控指标:

      
      # prometheus-alerts.yml
      groups:
        - name: dirty_page_alerts
          rules:
            - alert: DirtyPageSpike
              expr: |
                node_vmstat_nr_dirty / node_vmstat_nr_dirty_threshold > 0.7
              for: 30s
              labels:
                severity: warning
              annotations:
                summary: "Dirty pages approaching threshold on {{ $labels.instance }}"
                description: "Dirty page ratio: {{ $value | humanizePercentage }}"
            
            - alert: WritebackCongestion
              expr: |
                rate(node_vmstat_nr_written[1m]) < 1000
                and node_vmstat_nr_writeback > 500
              for: 1m
              labels:
                severity: critical
              annotations:
                summary: "Writeback IO congestion detected"
      

      六、总结

      在大规模 AI 训练场景中,Dirty Page 回写风暴是一个典型的"非计算性能瓶颈"。它不消耗 GPU FLOPS,不占用网络带宽,却能通过 IO 拥塞间接导致 GPU starvation,使得训练 throughput 下降 60-70%。

      防御这一问题的工程实践路线为:

      1. 预防:通过 O_DIRECT、fallocate 等方式降低脏页产生
      2. 提前:动态调整 vm.dirty_* 阈值,将回写提前分散到长时间段
      3. 隔离:使用 cgroup v2 io.max/io.weight 控制不同 IO 源的带宽
      4. 拦截:通过 BPF-LSM 在超限时限速脏页产生
      5. 监控:建立基于 bpftrace + Prometheus 的可观测体系
      6. 从深度学习框架到底层内核机制,横跨 memory 子系统、block layer、BPF 追踪技术的全栈联调思维,是高性能计算场景工程师必须掌握的核心技能。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部