尽管 CPU 温度正常,Kythe 代码索引进程仍受到限制

尽管 CPU 温度正常,Kythe 代码索引进程仍受到限制

我遇到了 CPU 限制问题,该问题似乎仅在运行特定工作负载时才会触发Kythe 索引器。问题末尾有详细的重现步骤。我将在这里给出一个高层次的总结。

Kythe 是一个从源代码中提取索引的工具。我在 GNU Parallel 下为 LLVM 中的每个编译单元运行 Kythe(并行将自动运行 32 个进程)。

以下工作负载能够持续最大化所有核心 10 分钟以上:

  • 使用 Ninja 进行 Clang 编译。此工作负载有点类似于索引,因为它应该执行类似数量的输入操作; Kythe 在内部使用 Clang 来索引代码。 CPU温度徘徊在75C - 80C左右。与运行 Kythe 的一个可能不相关的区别是 Kythe 可以生成大约 300MB ~ 2.5GB 的索引编译单元,所以我在一个小的 Python 包装器下运行 Kythe,该包装器创建一个临时文件,让 Kythe 写入它,然后删除该文件。
  • GNU Parallel 运行一个简单的繁忙循环(在 5-15 秒内按元素递增 1K 向量,这大约是 Kythe 索引编译单元所需的时间)。温度与上面类似。

然而,在 GNU Parallel 下运行 Kythe 会导致某种限制,CPU 降频,并且工作没有分配(使用sudo cpupower frequency-set -g performance没有帮助——所以问题似乎是 Kythe 进程在一段时间后受到惩罚/降低优先级) ,浏览器也会看到速度变慢)。温度降至60℃左右。

使用 Kythe 进行 CPU 节流

在上图中,图表的前半部分显示了 GNU Parallel/Busy 循环工作负载。然后,我终止这些进程并启动 GNU Parallel/Kythe 工作负载。由于某种原因,Kythe 工作负载会遇到限制问题,而 Clang 和 Busy 循环工作负载都不会遇到这些问题。可能是什么原因造成的/我如何进一步调试?

复制步骤

  1. (准备)在 LLVM 存储库上运行 CMake 命令:

    git clone https://github.com/llvm/llvm-project.git --depth=1
    cd llvm-project/llvm
    CC=/usr/bin/clang-14 CXX=/usr/bin/clang++-14 cmake -B ../build -DCMAKE_BUILD_TYPE=Release -G Ninja -DLLVM_ENABLE_PROJECTS=clang
    

    这将准备一个../build/compile_commands.json文件。

  2. (准备)下载 Kythe 版本(例如在 下$HOME/code)并按照 Kythe 文档中的描述运行提取器。

    wget https://github.com/kythe/kythe/releases/download/v0.0.60/kythe-v0.0.60.tar.gz -o $HOME/code
    tar xzf $HOME/code/kythe-v0.0.60.tar.gz
    cd ../build
    mkdir kythe-v0.0.60-output
    KYTHE_ROOT_DIRECTORY=$PWD KYTHE_OUTPUT_DIRECTORY=$PWD/kythe-v0.0.60-output/ KYTHE_CORPUS=my-llvm $HOME/code/kythe-v0.0.60/tools/runextractor compdb -extractor $HOME/code/kythe-v0.0.60/extractors/cxx_extractor
    
  3. (实际工作负载)并行运行Kythe:

    #!/usr/bin/env python3
    # code/timing.py
    
    import sys
    import tempfile
    import time
    import subprocess
    import os
    from datetime import datetime
    
    input_file = sys.argv[1]
    _, output_file = tempfile.mkstemp(prefix="entries-")
    
    start = datetime.now()
    subprocess.run(["/home/varun/code/kythe-v0.0.60/indexers/cxx_indexer", "--ignore_unimplemented", input_file, "-o", output_file])
    end = datetime.now()
    delta = end - start
    
    input_size = os.stat(input_file).st_size
    output_size = os.stat(output_file).st_size
    print("{} bytes to {} bytes in {} sec from {}".format(input_size, output_size, delta.seconds, input_file))
    
    os.remove(output_file)
    
    parallel ~/code/timing.py ::: kythe-v0.0.60-output/*.kzip | tee timings.txt
    

答案1

与运行 Kythe 的一个可能不相关的区别是,Kythe 可以为每个编译单元生成大约 300MB ~ 2.5GB 的索引,因此我在一个小型 Python 包装器下运行 Kythe,该包装器创建一个临时文件,让 Kythe 对其进行写入,然后删除文件。

事实证明,这是非常相关的。通过创建一个模拟 Kythe 的高磁盘输出的虚拟脚本并查看它是否会导致类似的限制,可以轻松检查这是否导致问题。这是一个示例脚本:

#!/usr/bin/env python3

import sys
import tempfile
import time
import os
import random
from datetime import timedelta
from datetime import datetime

output_fd, output_file = tempfile.mkstemp(prefix="entries-")

size_100M = random.randint(5, 15)

start = datetime.now()

# Kythe can end up writing about 500MB - 1.5GB in a span of 5-15s.
# We mimic that workload by writing 1M every 0.01s, and just wasting
# some CPU if we're done writing early.

dummyvec = list(range(1024))

for i in range(size_100M * 100):
    iter_start = datetime.now()
    iter_end = iter_start + timedelta(milliseconds=10)
    os.write(output_fd, os.urandom(1024 * 1024))
    while datetime.now() < iter_end:
        # Waste CPU
        for i in range(len(dummyvec)):
            dummyvec[i] = (dummyvec[i] + 1) % 1024

end = datetime.now()
delta = end - start

output_size = os.stat(output_file).st_size
print("Wrote {} bytes in {} sec".format(output_size, delta.seconds))

os.remove(output_file)

该脚本可以再次运行parallel

parallel high_output.py ::: kythe-v0.0.60-output/*.kzip

如果您开始看到超过 15 秒的计时,则可以肯定发生了限制。

事实证明,在parallel命令运行一段时间后,我开始看到超过 20-25 秒的时间。


查看其他温度也很重要,而不仅仅是 CPU 温度。例如,您可以lm-sensors在 Ubuntu 上使用该软件包来查看所有不同传感器的温度。

# Re-run sensors from lm-sensors every 2 seconds
watch -n 2 sensors

事实证明,问题出在 NVMe 驱动器的温度上。

nvme-pci-0400                                                                                                  
Adapter: PCI adapter                                                                                           
Composite:    +55.9°C  (low  = -273.1°C, high = +81.8°C)                                                       
                       (crit = +84.8°C)                                                                        
Sensor 1:     +55.9°C  (low  = -273.1°C, high = +65261.8°C)                                                    
Sensor 2:     +87.8°C  (low  = -273.1°C, high = +65261.8°C)          

在全速运行中,Kythe 最终可以为每个编译单元写入 100MB/s 的输出。虽然这还不错,但拥有 32 个进程意味着 3.2GB/s 的输出,在我的情况下这似乎压垮了 NVMe,导致过热。当 NVMe 驱动器过热时,Linux 似乎会限制所有正在运行的进程(解释了浏览器速度变慢的原因)。

特别是对于 Kythe,基于此Google 群组话题,Kythe 有一个标志--experimental_dynamic_claim_cache,看起来它可以通过在后台利用 memcached 来帮助减少磁盘输出。

相关内容