通常のCPU温度にもかかわらず、Kytheコードのインデックス処理が制限されています

通常のCPU温度にもかかわらず、Kytheコードのインデックス処理が制限されています

特定のワークロードを実行したときにのみ発生するCPU制限の問題が発生しました。Kythe インデクサー。再現のための詳細なステップは質問の最後にあります。ここでは、高レベルの要約を提供します。

Kytheはソースコードからインデックスを抽出するツールです。私はLLVMの各コンパイル単位に対してGNU ParallelでKytheを実行します(並列は自動的に32のプロセスを実行します)。

次のワークロードは、10分以上すべてのコアを継続的に最大化できました。

  • Ninjaを使ったClangコンパイル。このワークロードは、同じ数の入力操作を実行する必要があるという点で、索引付けに多少似ています。 Kythe は内部的に Clang を使用してコードをインデックスします。 CPU温度は75~80度程度となります。 Kytheの実行とは無関係の違いの1つは、Kytheが約300 MB〜2.5 GBのインデックスを作成できることです。すべてしたがって、一時ファイルを生成する小さなPythonラッパーでKytheを実行し、Kytheがファイルに書き込んでからファイルを削除します。
  • GNU Parallelは単純な忙しいループを実行します(5〜15秒で1Kベクトル要素を増やします。これはKytheがコンパイル単位をインデックス付けするのにかかる時間に似ています)。温度は上記と似ています。

しかし、GNU ParallelでKytheを実行すると、いくつかの制限、CPU制限、およびタスクは配布されません(使用しても役に立ちませんsudo cpupower frequency-set -g performance。したがって、問題はKytheプロセスがしばらくすると不利益になるか、優先順位が下がるようです)。ブラウザの速度低下を参照してください。)温度は約60℃まで低下します。

CPU調整にKytheを使用する

上の図では、チャートの前半はGNU並列/使用中のサイクルワークロードを示しています。その後、これらのプロセスを終了して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のマニュアルに記載されているようにExtractorを実行します。

    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の実行とは無関係の違いの1つは、Kytheがコンパイル単位あたり約300 MB〜2.5 GBのインデックスを生成できることです。したがって、Kytheが書き込むことができる一時ファイルを作成し、ファイルを削除する小さなPythonラッパーで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-sensorsUbuntuでこのパッケージを使用してさまざまなセンサーの温度を表示できます。

# 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 グループのトピック--experimental_dynamic_claim_cache、Kytheにはバックグラウンドでmemcachedを利用してディスク出力を減らすのに役立つフラグがあります。

関連情報