低周波数だからといって深いアイドル状態にあるわけではなく、performance モードだからといってアイドル状態の遷移が禁止されているわけではありません。CPUFreq はアクティブ時のパフォーマンスを管理し、CPUIdle はアイドル状態を管理します。比較する際には、電力、稼働時間、およびエネルギー を区別する必要があります。
ドライバー、属性、デフォルトのポリシーはカーネルやハードウェアによって異なります。実際の policy と実行状態を基準としてください。
参照目標 参照箇所
パフォーマンス要求とハードウェアの自治 CPUFreq、governor、schedutil、ベンダーモード
アイドルと配置 CPUIdle、EAS
証拠と比較の基準 読み取り専用チェック、エネルギー比較
CPU 電源管理の3つの意思決定層
スケジューラ
タスクをどのCPUに配置するか
CPUFreq
アクティブ時にどのようなパフォーマンスを要求するか
CPUIdle
タスクがない場合にどの程度の深さでアイドル状態に入るか
ハードウェア、ファームウェア、プラットフォームの制約
共有電源ドメイン、温度、電力予算、ウェイクアップレイテンシ
各層は相互に影響しますが、1つのアルゴリズムがCPU、周波数、アイドル状態を同時に一元的に選択するわけではありません。
CPUFreq の制御単位は policy です
CPUFreq core は汎用インターフェースを管理し、governor は負荷などの情報に基づいてパフォーマンス要求を選択し、driver は具体的なハードウェアインターフェースとやり取りします。一部のドライバーは汎用 governor をバイパスし、独自の制御アルゴリズムを提供できます。
複数の論理 CPU がパフォーマンス制御インターフェースを共有し、同じ cpufreq_policy に対応することがあります。sysfs の policyX はより明確な観測単位であり、cpuN/cpufreq を個別に読み取ると、同じポリシーが重複して表示される可能性があります。CPUFreq
governor 名はドライバーと合わせて解釈する
汎用 governor 主要な戦略 導き出すべきでない結論
performance policy が許可する最高周波数を要求 常に最高実測周波数に達する、レイテンシがゼロである
powersave policy が許可する最低周波数を要求 作業全体で消費される総エネルギーが必ずしも最小ではない
schedutil スケジューラが提供する利用率などの信号を使用 チック上でのみ実行される、CFS の単一カウンタのみを参照する
ondemand 利用率のサンプリングに基づいて調整 すべてのシナリオで他の戦略よりも劣る
conservative 要求をより漸進的に調整 ドライバーの遷移レイテンシやワークロードを無視できる
周波数要求は policy の上下限によって制約され、実際の実行は温度、電力予算、およびハードウェアの自治の影響も受けます。scaling_cur_freq は、ドライバーの最後の要求またはアーキテクチャが提供する推定値を反映していることが多く、ファイルを読み取った瞬間の実際のクロック周波数であるとは限りません。
schedutil がスケジューラに近い理由
タスクのキューイング、デキュー、周期更新などのイベントは、scheduler tick のたびに発生するのではなく、利用率の更新をトリガーします。周波数の不変性情報、容量、RT/DL 負荷、I/O wait boost、利用率制限、および更新レート制限などが、実際のパスに関与する可能性があります。
ドキュメントにある利用率に比例する公式は、目標を理解するのに役立ちます。負荷が容量に近づくほど、要求は高くなります。ただし、これは実装全体をカバーする正確な擬似コードではありません。ドライバーが高速切り替えをサポートしている場合は直接更新できますが、そうでない場合は他の実行コンテキストを介して完了する場合があります。ソースコードのエントリポイントは kernel/sched/cpufreq_schedutil.c です。
Intel と AMD のハードウェア自治モード
intel_pstate の active モードは、独自の performance/powersave アルゴリズムを提供し、HWP が利用可能な場合は、要求範囲と優先度に基づいてハードウェアがパフォーマンスを選択することもできます。ここでの powersave は、汎用の powersave が最低周波数を固定要求することとは異なります。passive モードでは、通常 scaling_driver 内で intel_cpufreq として表示され、汎用 governor によって要求が発行されます。intel_pstate
amd-pstate は CPPC パフォーマンスインターフェースに基づいており、その能力はプロセッサ、ファームウェア、および設定に依存します。passive、active、guided の違いは、ソフトウェアとハードウェアがパフォーマンス選択をどのように分担するかです。active では通常 EPP 優先度が関与し、guided ではハードウェアが指定された範囲内で選択に参加します。「Zen2+」だからといって、すべてのマシンが同じモードを有効にしているとは限りません。amd-pstate
CPUIdle:残留時間の利益とウェイクアップのコスト
アイドル governor は、予測されるアイドル時間、次のタイマーイベント、およびレイテンシ制約に基づいて、ドライバーが提供する idle state を選択します。重要なパラメータは、退出レイテンシと、その状態に入る価値がある目標残留時間(residency)です。
あるアイドル状態の目標残留時間が 100 μs、退出レイテンシが 20 μs であると仮定します。
条件 進入が不適切な理由
予測アイドル時間が 30 μs のみ 短すぎるため、十分な残留利益を得られない可能性がある
レイテンシ制約が最大 5 μs 20 μs の退出レイテンシは制約を満たさない
予測されるアイドル時間が長くても、ウェイクアップレイテンシを無視してはいけません。上記はモデルのパラメータであり、ある C-state の統一指標ではありません。
C1、C6 などの名称、実際の電源動作、およびレイテンシはプラットフォームによって異なります。コアとパッケージ全体の状態も異なります。特定のコアが深いアイドル状態を要求しても、共有電源ドメインがすぐに電源をオフにするとは限りません。固定されたマイクロ秒表を暗記するのではなく、ドライバーが公開する状態と実際の残留統計を読み取るべきです。CPUIdle
menu と TEO は異なる予測とフィードバック戦略を使用します。どちらが有効で、どちらが効果的かは、設定と負荷に依存しており、常に優れているデフォルトの勝者はいません。
2つの制約で候補状態をフィルタリングする
予測されるアイドル時間と許容される退出レイテンシを2つの独立した軸に配置することで、「アイドル時間が長いのに浅い状態を選ぶ」理由を説明できます。以下に、4つの人工的な状態を示します。深さの順序はこの例のためだけです。
状態 目標残留時間 μs 退出レイテンシ μs
poll 0 0
shallow 10 2
deep 100 20
deeper 1000 100
states = [ ( " poll" , 0 , 0 ) , ( " shallow" , 10 , 2 ) ,
( " deep" , 100 , 20 ) , ( " deeper" , 1000 , 100 ) ]
def choose ( predicted_us , latency_limit_us ) :
assert predicted_us >= 0 and latency_limit_us >= 0
allowed = [ name for name , residency , latency in states
if residency <= predicted_us and latency <= latency_limit_us ]
return allowed [ - 1 ]
assert choose ( 30 , 50 ) == " shallow" assert choose ( 500 , 5 ) == " shallow" assert choose ( 500 , 50 ) == " deep"
assert choose ( 100 , 20 ) == " deep" assert choose ( 5000 , 0 ) == " poll"
assert choose ( 5000 , 100 ) == " deeper"
このコードは制約の積集合を示すだけであり、menu や TEO の実装ではありません。実際の governor は、状態の無効化、履歴フィードバック、タイマーと tick などの条件も処理します。非同期割り込みが予測時間前に発生する可能性もあります。目標残留時間が 100 μs であっても、ハードウェアが少なくとも 100 μs のスリープを保証するものではなく、それに基づいて実際のウェイクアップイベントの処理を遅らせることはできません。CPUIdle:目標残留時間と退出レイテンシ
予測されるアイドル時間と許容される退出レイテンシを個別に調整します。候補はまず2つのハードルを満たし、次に出入りのオーバーヘッドを含む総エネルギーを比較します。最も深い状態が、あらゆる短いアイドルウィンドウの最適解であるわけではありません。
E i [ μ J ] = C i [ μ J ] + 1000 P i [ mW ] T [ μ s ]
まず、T が目標残留時間以上であり、退出レイテンシが制約を超えていないことを要求し、その後、総エネルギーを比較します。C はこの図で仮定された出入りのエネルギーコストであり、Linux governor の統一スコアリング公式ではありません。
図を準備しています 再読み込み
アイドル時間が十分長ければ、必ず最も深い状態に入れますか? 目標残留時間は進入する価値があるかどうかを衡量しますが、退出レイテンシは QoS を満たす必要があります。非常に長い予測アイドル時間でも、厳しいウェイクアップレイテンシ制限をカバーすることはできません。
{"id":"idle-state-eligibility","title":"アイドル時間が十分長ければ、必ず最も深い状態に入れますか?","summary":"目標残留時間は進入する価値があるかどうかを衡量しますが、退出レイテンシは QoS を満たす必要があります。非常に長い予測アイドル時間でも、厳しいウェイクアップレイテンシ制限をカバーすることはできません。","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"control\"><label for=\"idle\" data-i18n=\"idle\"></label><output for=\"idle\" id=\"idle-value\"></output><input id=\"idle\" type=\"range\" min=\"20\" max=\"5000\" value=\"1000\" step=\"20\"></div><div class=\"control\"><label for=\"qos\" data-i18n=\"qos\"></label><output for=\"qos\" id=\"qos-value\"></output><input id=\"qos\" type=\"range\" min=\"0\" max=\"150\" value=\"50\" step=\"5\"></div><p class=\"caption\" data-i18n=\"states\"></p><div class=\"states\"><div class=\"idle-state\" id=\"state-0\"><header>POLL<span id=\"eligible-0\"></span></header><p id=\"params-0\"></p><div class=\"band\"><i id=\"energy-0\"></i></div><strong id=\"e-0\"></strong></div><div class=\"idle-state\" id=\"state-1\"><header>S1<span id=\"eligible-1\"></span></header><p id=\"params-1\"></p><div class=\"band\"><i id=\"energy-1\"></i></div><strong id=\"e-1\"></strong></div><div class=\"idle-state\" id=\"state-2\"><header>S2<span id=\"eligible-2\"></span></header><p id=\"params-2\"></p><div class=\"band\"><i id=\"energy-2\"></i></div><strong id=\"e-2\"></strong></div></div><div class=\"metrics\"><div><span data-i18n=\"winner\"></span><strong id=\"winner\"></strong></div><div><span data-i18n=\"energy\"></span><strong id=\"energy\"></strong></div></div><div class=\"formula\" id=\"formula\"></div><div class=\"copy\"><p id=\"explanation\" role=\"status\"></p><p class=\"reserve\" aria-hidden=\"true\" data-i18n=\"note\"></p></div><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:500;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:500 20px var(--viz-font-ui)}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:var(--viz-font-mono);font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px var(--viz-font-ui);background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n.idle-state{padding:14px;border:1px solid var(--rule);border-radius:8px;margin:12px 0}.idle-state header{display:flex;gap:10px;justify-content:space-between;font-size:13px;min-height:3.2em}.idle-state header span{color:var(--muted);font-size:12px;max-width:65%;text-align:right}.idle-state p{font-size:12px;min-height:3.2em;margin:8px 0}.idle-state strong{display:block;font:12px var(--viz-font-ui);text-align:right;margin-top:7px}.idle-state.chosen{border-color:var(--accent);background:var(--accent-soft)}.idle-state.ineligible .band{opacity:.4}.formula{min-height:5em}","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const states=[{name:'POLL',res:0,lat:0,power:1000,cost:0},{name:'S1',res:100,lat:20,power:100,cost:5},{name:'S2',res:1000,lat:100,power:10,cost:30}];function draw(){const idle=+$('#idle').value,qos=+$('#qos').value,energies=states.map(s=>s.cost+s.power*idle/1000),eligible=states.map(s=>idle>=s.res&&s.lat<=qos);let winner=0;for(let i=1;i<3;i++)if(eligible[i]&&energies[i]<energies[winner])winner=i;set('idle-value',idle+' μs');set('qos-value',qos+' μs');states.forEach((s,i)=>{$('#state-'+i).classList.toggle('chosen',i===winner);$('#state-'+i).classList.toggle('ineligible',!eligible[i]);set('eligible-'+i,(eligible[i]?'✓ ':'× ')+t(idle<s.res?'short':s.lat>qos?'slow':'eligible'));set('params-'+i,t('residency')+' '+s.res+' μs · '+t('exit')+' '+s.lat+' μs');$('#energy-'+i).style.width=energies[i]/Math.max(...energies)*100+'%';set('e-'+i,viz.number(energies[i],1)+' μJ');});set('winner',states[winner].name);set('energy',viz.number(energies[winner],1));const s=states[winner];set('formula','E = '+s.cost+' μJ + '+s.power+' mW × '+idle+' μs / 1000\\n= '+viz.number(energies[winner],1)+' μJ');set('explanation',t('note'));}$('#idle').oninput=$('#qos').oninput=draw;draw();","audio":false,"strings":{"eligible":"両方を満たす","energy":"推定エネルギー / μJ","exit":"退出レイテンシ","heading":"アイドル時間が十分長ければ、必ず最も深い状態に入れますか?","idle":"予測アイドル時間 / μs","intro":"予測されるアイドル時間と許容される退出レイテンシを個別に調整します。各状態の2つの資格と推定エネルギーを比較し、最終的に選択可能な状態を確認します。","note":"予測アイドル時間を延ばし、QoS を厳しくします。深い状態はエネルギー消費が低くなる可能性がありますが、資格は退出レイテンシによって妨げられるため、エネルギーバーが最短だからといって選んではいけません。","qos":"許容退出レイテンシ / μs","reset":"リセット","residency":"目標残留時間","scope":"3つの純粋な教育用オプション:POLL、S1、S2。パラメータはプラットフォームの C-state に対応しません。資格は、予測時間が目標残留時間以上かつ退出レイテンシが QoS 以下であり、推定エネルギーが最小のものを選択します。E=固定変換エネルギー+アイドル電力×予測時間。これは簡略化されたコストモデルであり、Linux governor を再現するものでも、予測の正確性を保証するものでもありません。","scopeLabel":"モデルの範囲と規約","short":"予測時間が短すぎる","slow":"退出レイテンシが制約を超える","states":"各項目の資格と推定エネルギー","winner":"モデルの選択"}}
EAS はタスク配置のエネルギー推定
Energy Aware Scheduling(EAS)は、Energy Model などの情報を使用して、タスク配置のエネルギー影響を比較します。特に容量が非対称な CPU に関連します。EAS は利用率推定やパフォーマンス調整と関連していますが、cpuidle と cpfreq を1回の統一意思決定に統合するものではなく、単純にウェイクアップ済みの CPU を優先選択するものでもありません。EAS
過負荷、モデルがない、または有効化条件を満たさない場合、EAS が機能していると仮定してはいけません。アーキテクチャを横断して理解する際は、ARM 固有のスイッチとして貼るだけでなく、モデルとスケジューリング条件に注目すべきです。
現在のマシンでの読み取り専用チェック
以下では、Python を使用して既存の sysfs 属性を列挙し、異なるドライバーでフィールドが欠落している場合にコマンドのエラーを故障と見なさないようにしています。
from pathlib import Path
base = Path ( ' /sys/devices/system/cpu' )
for policy in sorted ( ( base / ' cpufreq' ) . glob ( ' policy*' ) ) :
print ( policy . name )
for key in ( ' related_cpus' , ' scaling_driver' , ' scaling_governor' ,
' scaling_min_freq' , ' scaling_max_freq' , ' scaling_cur_freq' ,
' energy_performance_preference' ) :
path = policy / key
if path . exists ( ) :
print ( ' ' , key , path . read_text ( ) . strip ( ) )
for state in sorted ( ( base / ' cpu0/cpuidle' ) . glob ( ' state*' ) ) :
print ( state . name )
for key in ( ' name' , ' latency' , ' residency' , ' usage' , ' time' ) :
path = state / key
if path . exists ( ) :
print ( ' ' , key , path . read_text ( ) . strip ( ) )
周波数属性は通常 kHz で表され、idle の latency/residency/time 関連インターフェースは通常マイクロ秒で表されます。usage は累積的な進入回数です。統計は、一定期間の増分を比較すべきであり、起動以来の累積量を現在のパーセンテージとして扱うべきではありません。コンテナや仮想マシン内で見える機能は、物理ホストと異なる場合があります。
ポリシーを比較する際は、時間とエネルギーの両方を見る
電力は瞬時の消費率であり、エネルギーは電力の時間に対する積分です。低電力でも作業時間が長くなれば、必ずしもエネルギーを節約できるわけではありません。完了が速く、その後アイドル状態に入っても、すべての負荷で最適であるとは限りません。スループットまたは完了時間、テールレイテンシ、エネルギー、温度を少なくとも比較し、タスク、バックグラウンド負荷、および測定範囲を一定に保つ必要があります。
同じ 100 ms ウィンドウで、高速完了と低電力の結果が逆転する可能性がある
100 ms ごとに同じ作業を完了し、同じ電源ドメインを測定し、アクティブ時とアイドル時の電力が各セグメント内で一定であると仮定します。切り替えエネルギーを無視し、アイドル電力を一律 1 W とします。
方案 アクティブ段階 残りのアイドル段階 1サイクルの総エネルギー
高速完了 10 W × 20 ms 1 W × 80 ms 0.28 J
低いアクティブ電力 6 W × 50 ms 1 W × 50 ms 0.35 J
より高いアクティブ効率 4 W × 50 ms 1 W × 50 ms 0.25 J
同じ作業、同じサイクル:アクティブ時とアイドル時の両方がエネルギーに含まれる
高速
10 W × 20 ms
1 W アイドル
0.28 J
低速
6 W × 50 ms
1 W アイドル
0.35 J
棒の長さは時間を表します。エネルギー = 各段階の電力 × 時間の合計
100 ms サイクルの教育用データであり、実際の CPU の周波数、電力、または状態切り替えコストは表していません。
2行目はアクティブ電力が低いですが、実行時間が長いため、サイクルエネルギーは逆に高くなります。3行目はアクティブ電力をさらに低下させた結果、勝利しました。したがって、race-to-idle と周波数低下の両方を測定でサポートする必要があり、ポリシー名から答えを導き出すことはできません。完了期限が 40 ms の場合、後2行はエネルギーが低くても、このタスクのタイムリミットを満たしません。
from fractions import Fraction
def cycle_j ( active_w , active_ms , idle_w = 1 , period_ms = 100 ) :
assert 0 <= active_ms <= period_ms
return Fraction ( active_w * active_ms + idle_w * ( period_ms - active_ms ) , 1000 )
fast = cycle_j ( 10 , 20 )
slow = cycle_j ( 6 , 50 )
efficient = cycle_j ( 4 , 50 )
assert ( fast , slow , efficient ) == ( Fraction ( 28 , 100 ) , Fraction ( 35 , 100 ) , Fraction ( 25 , 100 ) )
assert efficient < fast < slow
assert fast / Fraction ( 100 , 1000 ) == Fraction ( 28 , 10 ) assert 20 <= 40 < 50
実際のテストでは、2回の完了で同じ作業量が完了したことを確認し、周波数の変化が本当にボトルネックに影響しているかを記録する必要があります。例えば、メモリや I/O を待機するタスクは、コア周波数に比例して加速できない可能性があります。より長いアイドル時間が、パッケージをより深い状態に遷移させるとは限りません。バックグラウンド作業が存在する場合は、測定ドメインの総エネルギーとベースライン処理方法を同時に報告する必要があり、全体のバックグラウンド変化をすべて governor に帰因してはいけません。
測定範囲:電源ドメインのエネルギーはコンセントの全体消費電力ではない
RAPL などのカウンターは特定の電源ドメインのエネルギーを反映しており、コンセントの全体消費電力ではありません。カウンターはラップアラウンドすることもあります。さらに、全体のスリープと単一デバイスの runtime PM を区別するには、スリープとウェイクアップ を参照してください。
累積カウントをどのように区間指標に変換するか
同じ idle state が 2 秒の観察区間で、time が 500000 μs 増加し、usage が 200 増加した場合、ソフトウェアが記録した残留割合は 25% となり、各進入時の平均記録時間は 2500 μs となります。これはあくまでその CPU、その状態の区間統計であり、4つの CPU の割合を単純に足し合わせても、単一 CPU としてのパーセンテージは得られません。ドライバーが要求した状態のソフトウェア統計は、ハードウェアパッケージの実際の残留カウントと一致する必要はありません。
エネルギーカウンターは、まず差分を求め、経過時間で割ります。範囲 R でラップアラウンドし、リセットされていないカウンターの場合、(after-before) % R で R を法とした増分を求められます。真の増分が R より小さいことがわかっている場合のみ、それを実際のエネルギー差として扱うことができます。間隔が長すぎる場合、後方の数値が前方の数値より大きくても、すでに1周ラップアラウンドしている可能性があります。
assert 500_000 / 2_000_000 == 0. 25
assert 500_000 / 200 == 2500
span_uj , before_uj , after_uj = 1000 , 950 , 30
observed_delta = ( after_uj - before_uj ) % span_uj
assert observed_delta == 80
assert ( before_uj + 80 ) % span_uj == after_uj
assert ( before_uj + 1080 ) % span_uj == after_uj
energy_uj と max_energy_range_uj の単位は μJ です。読み取る具体的な zone が統計範囲を決定します。親 zone と子 zone は重複するハードウェアをカバーする可能性があるため、パッケージとそのすべての子ドメインのエネルギーを単純に足し合わせて総量として仮定してはいけません。サンプリング間隔、ラップアラウンド範囲、カウンターのリセット、およびドメイン名は、結果とともに保持されるべきです。Powercap インターフェース