GPU(RTX3090)の冷却検討+消費電力を動的に変えるスクリプト


※下書きをGPT-4が修正した文章+αです。

はじめに

現在、私たちは大規模言語モデルの訓練にRTX3090というGPUを利用しています。RTX3090は、コンシューマー向けの製品であるため、熱設計にいくつかの問題が存在します。
理論上、このGPUは350Wの電力で安定して運用することができるはずですが、実際には、GPUの温度が70℃を大きく上回ることを防ぐために、消費電力を下げる必要があります。
そうしないと、過熱によりサーマルシャットダウンが発生し、結果としてGPUが応答せず、マシンを再起動する必要が生じます。

計算速度と消費電力の関係は、概ね線形に近い関係にあると考えられます。つまり、数日間にわたる訓練を行う際には、可能な限り高い出力でGPUを運用したいと考えるのが自然です。
この記事では、そのような条件下でGPUの出力を最大化するための、試行錯誤の過程をメモとして記録しています。

環境

このマシンは、以下のカスタマイズされたワークステーションの仕様を持っています。

CPUには水冷システムが搭載されており、Threadripper 3990Xを100%の使用率で持続的に稼働させることができる性能があります。
しかし、RTX 3090に関しては、350Wでの100%の使用率を数時間維持しようとすると、先に述べたような問題で頻繁にシャットダウンする事態※に直面します。
ここでの「※」は、購入から2、3年経過した現在の状況を指しており、購入直後には長時間の連続使用を行っていなかったため、冷却性能の問題がマシン自体の設計に起因するものなのか、それとも経年劣化やその他の要因によるものなのかは明確ではありません。

ホコリに関しては、外部のケースに対する軽度のメンテナンスは行っていますが、筐体を解体しての徹底的な清掃は行っていません。
これが冷却性能に影響を及ぼしている可能性も考えられます。
定期的な内部清掃は、ホコリによる断熱効果を低減し、冷却性能の改善に寄与する可能性があるため、検討する価値があります。また、放熱に関しては、ケース内のエアフローの改善や、より高性能の冷却システムへのアップグレードも有効な対策となり得ます。


対策

水冷の検討(未実施)

市販されているパーツを使用し、RTX3090を水冷化する改造が可能なようです。その効果は非常に顕著であるとの報告がありますが、私は改造経験がなく、また、改造によって何らかの故障を引き起こした場合のリスクや、改造作業の煩雑さを考慮し、現段階では実施に至っていません。


環境整備

筐体のホコリを取り除いたところ、マシンの冷却状態が改善されました。さらに、ケースが前面を開放可能なタイプだったため、そこを開けておくことで空気の流通を良くしました。

その上で、部屋には冷房を設定し19℃に保つことで、マシンに冷気が直接当たるようにしました。記事の執筆日は11月4日で秋季に当たりますが、それにもかかわらず最高気温が約25℃に達し、マシンにとっては過剰に暑い環境となっています。その結果、部屋の温度も高めでした。

マシンの様子: ラックを買うべきです。

消費電力を動的に変えるスクリプトを書く

Linux系OSにおいては、nvidia-smi コマンドに適切な引数を設定することでGPUの消費電力を調整することが可能です。たとえば、GPU番号0の消費電力を170Wに設定する場合、以下のコマンドを使用します。

sudo nvidia-smi -i 0 -pl 170

最適な消費電力の値を見つけるためには、GPUの温度を常に監視し、部屋の温度やGPUの状態に応じて変化させる必要があります。
そのため、GPUの温度をモニタリングしつつ、消費電力を動的に変更するシェルスクリプトを作成しました。このスクリプトは、GPT-4を参考にしながら作成されたものです。

#!/bin/bash

 #GPU id
GPU_ID=0

#電力の初期値
CURRENT_POWER_LIMIT=230

# 電力制限を設定する温度閾値
TEMP_THRESHOLD=70

# 電力制限を設定するワット数の範囲
POWER_LIMIT_MIN=170
POWER_LIMIT_MAX=350
# 電力制限のステップ
POWER_STEP=10

while true; do
    # 現在のGPU温度を取得
    GPU_TEMP=$(nvidia-smi -i $GPU_ID --query-gpu=temperature.gpu --format=csv,noheader,nounits)

    # 温度が閾値を下回るか確認し、電力制限を調整
    if [ "$GPU_TEMP" -lt "$TEMP_THRESHOLD" ]; then
        # 電力制限を増やすが、最大値を超えないようにする
        NEW_POWER_LIMIT=$((CURRENT_POWER_LIMIT + POWER_STEP))
        if [ "$NEW_POWER_LIMIT" -gt "$POWER_LIMIT_MAX" ]; then
            NEW_POWER_LIMIT=$POWER_LIMIT_MAX
        fi
        # 新しい電力制限を適用
        sudo nvidia-smi -i $GPU_ID -pl $NEW_POWER_LIMIT
        CURRENT_POWER_LIMIT=$NEW_POWER_LIMIT

    else
        # 電力制限を減らすが、最小値を下回らないようにする
        NEW_POWER_LIMIT=$((CURRENT_POWER_LIMIT - POWER_STEP))
        if [ "$NEW_POWER_LIMIT" -lt "$POWER_LIMIT_MIN" ]; then
            NEW_POWER_LIMIT=$POWER_LIMIT_MIN
        fi
        # 新しい電力制限を適用
        sudo nvidia-smi -i $GPU_ID -pl $NEW_POWER_LIMIT
        CURRENT_POWER_LIMIT=$NEW_POWER_LIMIT
    fi

    # 一定時間(例えば5秒)ごとにチェック
    sleep 60
done

設定した閾値(70℃)を下回っていたら、消費電力を+10W、下回っていたら-10Wする単純なプログラムです。

主な変数の説明

  • GPU_ID: 制御するGPU番号(=0)

  • CURRENT_POWER_LIMIT: ワット数の初期値(=230W)

  • TEMP_THRESHOLD: 電力を制限する閾値(70℃)

    • この温度を超えると、CURRENT_POWER_LIMITを+10℃(=POWER_STEP)

    • 下回ると、-10℃

  • 設定電力の上限、下限

    • POWER_LIMIT_MIN=170

    • POWER_LIMIT_MAX=350

  • sleep 60

    • 60秒ごとに監視


頻繁に消費電力を変えてもよいのか、不安なところですが、GPT-4的には、そこまで大きな問題はないのでは、との回答でした。

結果

元々は170Wあたりが限界だったのですが、250-290Wくらいで運用できるようになりました。
計算速度も1.5-2倍くらいに上がりました。

最大出力350Wを実現するには、水冷する、冬を待つ などの選択肢を考える必要がありそうです。


この記事が気に入ったらサポートをしてみませんか?