コグノスケ


2019年 4月 1日

簡易 CPU 消費電力測定

簡易的に CPU の消費電力を測ってみました。測定ポイントは ATX 電源と AC コンセントの間です。要はワットチェッカーで PC 全体の消費電力を測っています。

アイドル状態から 1スレッド、2スレッド、と負荷を増やし、
(負荷時の消費電力) - (アイドル時の消費電力) = CPU の消費電力
と見なしています。負荷には仮想通貨のマイニングソフトのベンチマークモードを使っています。それなりに複雑な計算と、スレッド数の制御が容易いので便利です。

Ryzen 7 2700 の TDP は 65W なのに、消費電力が 70W 以上に計算されるところからわかるように、消費電力は若干多めに出ています。おそらく CPU の負荷に連動して冷却ファンが回ること、ATX 電源の変換効率が負荷によって変わること、などが原因だと思われます。


スレッド数と消費電力

Ryzen 7 2700 は 8コア 16スレッドですが、5スレッドを超えた辺りから、フルパワーの消費電力とあまり差がなくなります。


スレッド数と電力効率

また W 辺りの計算効率(kH/s・W)を計算すると、16並列が一番効率が良いです。逆に 5〜6 スレッド程度だと効率が悪いです。中途半端な並列度で計算するくらいなら、16 スレッドフルに使いきれということですね。

コア優先で割り当てたらどうなるか?

上記の実験方法を見て「スレッドをどの CPU に張り付けるかを制御しなくても良いのか?」疑問に感じた方、さすがです。手抜きしていたことがバレましたね。

マイニングソフトのコードを見たら、ちょいと改造すれば簡単にスレッドの affinity を設定できそうだったので、改造してもう一度測りました。

まず Ryzen 7 2700 は SMT 構成になっていまして、1コアが 2スレッド実行可能(OS からは 1コア = 2 CPU として扱う)です。私の環境 Debian Testing だと、

  • CPU 0: コア 0 スレッド 0
  • CPU 1: コア 0 スレッド 1
  • CPU 2: コア 1 スレッド 0
  • CPU 3: コア 1 スレッド 1
  • ...

以上のように割り当たるようです。ここで素直に CPU 0 から順にスレッドの affinity を設定すると、1つのコアに 2スレッドずつ張り付きます。どういうことかと言いますと、4スレッド起動したとき、コア 0 とコア 1 に 2スレッドずつ張り付いて、他の 6コアはヒマになるということです。これはあまり効率が良くなさそうですよね?

今回の測定では、コアを使い切ることを優先してスレッドを割り当てました。当然ながら 16スレッドの性能は変わらないのですが、途中の傾向が少し変わります。


スレッド数と消費電力、コア優先割り当て

消費電力は 4コアの時点でピークにかなり近くなります。8コアじゃないのは何ででしょうね?2コアがペアで電源制御されているんでしょうか……?


スレッド数と電力効率、コア優先割り当て

電力効率は 8スレッドが最大で、16スレッドに向かってやや下がります。SMT の特徴が出ている感じがします。

メモ: 技術系の話は Facebook から転記しておくことにした。多少修正。

編集者: すずき(更新: 2019年 4月 2日 00:33)

コメント一覧

  • hdk 
    去年Ryzen 7 1700で測りましたがやはりTDPより少し高めでした: http://www.e-hdk.com/diary/d201808b.html#15-1 
    (2019年04月02日 22:48:26)
  • すずき 
    どの CPU というかシステムでも同じ傾向ですね。CPU の消費電力だけ測れているわけではないですし、そんなもんかなーと思いました。 
    (2019年04月05日 11:03:13)
open/close この記事にコメントする



2019年 4月 12日

ぼやける Windows

以前の日記(2019年 3月 17日の日記参照)で、Windows Update のあとにウインドウのタイトルがズレてしまう話を書きました。

その際に同時に発生する画面がぼやけてしまう現象についてもスクリーンショットを取ったので載せておきます。


ボヤけている状態

このようにフォントがボヤけてしまいます。タスクマネージャの場合はあまり目立ちませんが、アプリケーションによってはさらに顕著です。


サインアウト、サインインしなおした状態

前回は「再起動で直る」と書きましたが、サインインしなおすだけでも直るようです。

ボヤける理由の予想

ざっくりいうと、Windows Update がテキストサイズの拡大縮小設定を元に戻した後に、サインインしなおさないからじゃないか?と思っています。

Windows 10 にはアプリケーションのテキストサイズを調整する機能があります。[Windows の設定] -> [システム] -> [ディスプレイ] から設定できます。


拡大縮小設定を変更したときの警告文

設定変更すると一部のアプリは、サインアウトするまで、拡大縮小の設定に応答しません、という警告文が表示されます。

購入当初は 125% の設定になっていました。初期値はディスプレイの物理的なサイズと解像度によって決まっているそうです。あと、私は拡大縮小の設定を「100%」に変更して使用しています。

以上から導いた私の予想ですが、

  • Windows Updateによって、テキストサイズの設定が初期値(125%)に戻る
  • Windows Update が PC を再起動する
  • アプリケーションがテキストサイズ 125% で表示する
  • Windows Update がユーザーが使っていたテキストサイズ設定(私の場合 100%)に設定しなおす
  • サインアウトは行わないため、アプリケーションがついてこられずボヤけてしまう

こんな状態になっているのではないかと思っています。

編集者: すずき(更新: 2019年 4月 13日 17:06)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2019年 4月 13日

レジスタダンプ、書き換えツール memaccess - ちょっと修正

先日(2019年 3月 24日の日記参照)作った memaccess(GitHub へのリンク)細かい部分が色々バグっていたので直しました。

  • 32bit 環境でビルドできない
  • ビルド時に libtool を要求する(本来は要らない)
  • 0x80000000_00000000 以上のアドレスを指定すると 0x7fffffff_ffffffff になってしまう
  • 32bit を超える値を書き込めない

アドレスの指定は文句なしで 64bit 符号なし整数にしましたが、書き込む値については 64bit の符号つき整数(今はこっち)と 64bit の符号なし整数の、どっちが良いんでしょうね。贅沢を言えば、どちらも使いたいですけど。

編集者: すずき(更新: 2019年 4月 19日 23:35)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2019年 4月 18日

Linux の DMA

昨今のキャッシュを持った CPU では、DMA を行う際に CPU のキャッシュのフラッシュ(ダーティデータをメインメモリに書きだす、パージともいう)やインバリデート(キャッシュから消しさる、クリーンともいう)が必須です。

しかしアーキテクチャや CPU の実装によってキャッシュの操作方法は異なるため、Linux では DMA API というレイヤでアーキテクチャの差分を隠蔽しています。

Linux で DMA を行うドライバを書くときの一番単純な作法(=単一の領域に DMA を行う、スキャッターギャザーなどはしない)は、

dma_alloc
バッファ確保
dma_map_single
バッファを CPU のメモリ空間にマップし、CPU から見えるようにする
dma_sync_single_for_cpu
CPU からバッファをアクセスする準備
CPU からバッファにデータを書き込む
dma_sync_single_for_device
デバイスからバッファをアクセスする準備
デバイスから DMA を行いデータを読み込む
dma_unmap_single
バッファのマップをやめる
dma_free
バッファ解放

ざっくりいってこのような感じです。先ほど述べた通り、Linux の DMA API にキャッシュのフラッシュやインバリデート関数はありません。ハード依存の操作をなるべく減らし、多数のアーキテクチャに対応しやすくなっているんですね。

実際はいつフラッシュしているのか?

そうはいっても、実際にどこでキャッシュフラッシュしているか、気になると思います。昔、Linux 4.4 を調べた情報を引っ張り出してきました。アーキテクチャは AArch64 つまり 64bit の ARM コアです。

AArch64 の場合、キャッシュ操作をしているのは dma_sync_single_for_cpu() と dma_sync_single_for_device() です。前者がインバリデート、後者がフラッシュ+インバリデートを行っています。

前者の dma_sync_single_for_cpu() を追いかけてみると、

dma_sync_single_for_cpu()
関数ポインタ経由で ops->sync_single_for_cpu() を呼びます。AArch64 の場合 ops には通常 swiotlb の DMA 操作関数が入っています。ですので __swiotlb_sync_single_for_cpu() が呼ばれます
__swiotlb_sync_single_for_cpu()
コヒーレントバッファでない(キャッシュフラッシュがいる)場合 __dma_unmap_area() を呼びます
__dma_unmap_area()
__dma_inv_range() を呼びます
__dma_inv_range()
キャッシュをインバリデートします

こんな感じですね。しつこいですが AArch64 の実装を見ただけですので、将来的に変わるかもしれないし、他のアーキテクチャでは仕組みが違います。

直接フラッシュしたがるおじさん

昔の Linux ではキャッシュ操作関数をドライバから使うことができました。その記憶からなのか、たまにフラッシュやインバリデートのようなアーキテクチャ依存の操作を直接呼びたがる人がいます。

今の Linux ではキャッシュ操作関数は当然ありますが、ドライバからは呼べない、つまり呼ぶことを推奨していません。もちろんオープンソースなので改造すれば何でもできますけど、メンテナンス性や再利用性、移植性を下げるだけで、損しかないでしょう。

編集者: すずき(更新: 2019年 4月 20日 00:29)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2019年 4月 19日

RISC-V SoC 搭載ボード探し

目次: RISC-V - まとめリンク

Linux が動くくらいの RISC-V の SoC 搭載ボードを探していたのですが、どうやらまだ市販されてなさそうでした……。

代わり(?)に SiFive の高性能 RISC-V SoC である HiFive Unleashed(リンク)のマニュアルを眺めていました。

HiFive Unleashed は高性能と紹介されていることが多いですが、現状 RISC-V は Arduino くらいの小規模 SoC がほとんどで、それらと比較して高性能、と言っているのだと思われます。

特に珍しい機能もないですし、最近のテレビやタブレット向けの巨大な ARM 系 SoC と比べると、どうしてもショボく見えてしまうのは仕方ないでしょう。

ああ、でも Errata の章があるのは珍しいかもしれません。

ROCK-2: High 24 address bits are ignored
Workaround
Do not access out-of-bound addresses in software.
I2C-1: I2C interrupt can not be cleared
Workaround
Poll the I2C controller state to wait for TIP (transaction in progress) to go low.

などの豪快なバグがある様子が伺えます。特に ROCK-2 の Workaround は全然 Workaround になっておらずのが面白いです。アクセス違反をするな、と言ってアクセス違反がなくなるなら OS の苦労はないでしょ。かなり悲惨なバグです。

ボードには修正した SoC を載せるのか、バグった SoC を強引に搭載するのか、どちらなんでしょうね……。

メモ: 技術系の話は Facebook から転記しておくことにした。

編集者: すずき(更新: 2021年 8月 21日 02:54)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2019年 4月 27日

クロスビルド用ツールチェーン - その 1

目次: GCC を調べる - まとめリンク

先日(2019年 3月 27日の日記参照)クロスビルド向け LLVM のビルド方法がわかったので、今度はクロスビルド向け GCC のツールチェーン(超基本的な binutils + GCC + glibc の組み合わせ)を作ろうとしていますが、さっぱりうまくいかないです。

そもそもどのバージョンの組み合わせならビルドが通るのか全くわかりません……。対象となるクロス環境(ARM 向けなのか、RISC-V 向けなのか)と、ホスト側のコンパイラバージョンが影響するようで、昔ビルドが通っていた組み合わせを引っ張り出してきても、今の環境だとビルドが通らないなんてことがおきます。

やりたいこと

ビルドできる組み合わせは頑張れば見つけられるとは思いますが、本来やりたいことはクロスビルド用のコンパイラのソースコードリポジトリをダウンロードし、自分でソースコードに何か変更を入れ、変更した内容も含めてビルドすることです(ダウンロードは最悪手動でも良いですけど)。

世の中にはクロスビルド用のツールチェーンを作成できるツールはいくつかありますが、いずれも tarball からのビルドを想定していて、改変を入れて再ビルドする方法が良くわかりません。

ツールが想定しているリリース用のビルドは、

  • リリースバージョンの tarball か、ソースコードリポジトリのリリースタグを持ってきてビルド
  • 実機で使える形、インストーラなどにパッケージング

開発用は、リリース用に加え、

  • 最新のソースコードリポジトリを持ってくる
  • ソースコードに素早くアクセス、改変
  • 改変した部分だけ差分ビルド
  • (必要なら)モジュールを足す

が必要ですが、意外とできないです……。

クロスビルド用ツールチェーンを作成できるツール

いくつかツールを調べてみました。

Yocto
ソースコードはアクセスしづらいです。例えば AGL(Yocto を使っています)は、
agl/build/tmp/work-shared/gcc-8.2.0-r0/gcc-8.2.0/
に置かれます。何回見ても覚えられません

ソースコードの改変はできますが、bitbake はソースコードの変更を認識しないようです。bitbake にモジュールを明示的に指定すれば良さそうです。もしくはパッチを作ってレシピに足して bitbake するのが Yocto 的には正しいのかな?どちらにせよ面倒です。

新たにモジュールを足す方法は、レシピを足すだけなので簡単だと思いますが、それ以外が辛すぎます。開発用には向いていません。
crosstool-NG
ソースコードは、
crosstool-ng/.build/src/gcc-8.2.0/
にあります。アクセスしやすいです。

ソースコードの改変は反映されますが、差分ビルドはしないようで、./ct-ng build とすると全てビルドしなおされます。ちょっと微妙です。

新たなモジュールの追加はどうやるのかわかりません。Yocto などとは違い、コンパイラなどのツールチェーンをビルドする専用ツールなので、Linux カーネルや busybox はビルドしません。足すものはあまりないんじゃないでしょうか。
buildroot
ソースコードは、
buildroot/output/build/host-gcc-final-7.4.0/
にあります。Yocto よりわかりやすいです。

ソースコードの改変は認識されていないように見えます。ソースコードを変更して make しても何もビルドされません

新たなモジュールの追加方法は知らないですが、比較的簡単なのかな…?

ツールチェーン単体だと crosstool-NG ですし、将来的に追加するものを考えると buildroot が良さそうですけど。変更を反映して差分ビルドする方法ないのかな……??

編集者: すずき(更新: 2021年 5月 20日 16:20)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2019年 4月 29日

クロスビルド用ツールチェーン - その 2

目次: GCC を調べる - まとめリンク

引き続き、超基本的な binutils + GCC + glibc の組み合わせのクロスビルド環境を作っています。やや苦戦したものの、ARM, AArch64, RISC-V 64 でビルドが通りました。良かった良かった。

残念ながら RISC-V 32 は glibc が対応しておらず、libc なしのベアメタル向けコンパイラしか作れませんでした。glibc does not yet support 32-bit systems と怒られます。glibc の代わりに newlib などを使えば、libc ありの Linux 向けコンパイラが作れるかもしれませんが、試していないのでわかりません。

環境

昔作ったクロスコンパイラをビルドする Makefile(GitHub へのリンク)を改造して、作りました。

前回(その 1)検討した通り、本格的に運用するなら独自のビルドツールより crosstool-NG か buildroot に切り替えた方が良いと思います。

ビルド方法

詳細は GitHub を見た方が良いですが、configure に指定しているオプションだけ、ざっと列挙しておきます。

変数の定義(イメージ)

CROSS_ARCH = riscv64-unknown-linux-gnu
TOP_DIR    = `pwd`
CROSS_ROOT = $TOP_DIR/buildroot

PREFIX  ?= $(CROSS_ROOT)
SYSROOT ?= $(CROSS_ROOT)/$(CROSS_ARCH)/sysroot

まず binutils は、

binutils の configure

./configure \
  --target=$(CROSS_ARCH) \
  --prefix=$(CROSS_ROOT) \
  --disable-nls \
  --disable-static \
  --disable-werror \
  --with-lib-path=$(CROSS_ROOT)/lib \
  --with-sysroot=$(CROSS_ROOT)

次に gcc は、

gcc 1回目 の configure

./configure \
  --target=$(CROSS_ARCH) \
  --prefix=$(PREFIX) \
  --enable-languages=c \
  --disable-libatomic \
  --disable-libitm \
  --disable-libgomp \
  --disable-libmudflap \
  --disable-libquadmath \
  --disable-libsanitizer \
  --disable-libssp \
  --disable-libstdcxx-pch \
  --enable-long-long \
  --enable-lto \
  --disable-multiarch \
  --disable-multilib \
  --disable-nls \
  --disable-plugin \
  --disable-shared \
  --disable-threads \
  --disable-__cxa_atexit \
  --without-headers \
  --with-local-prefix=$(SYSROOT) \
  --with-sysroot=$(SYSROOT) \
  --with-newlib

難関の glibc はこんな感じ、

glibc の configure

./configure \
  --host=$(CROSS_ARCH) \
  --prefix=$(SYSROOT)/usr \
  --disable-profile \
  --disable-multilib \
  --enable-add-ons \
  --enable-kernel=3.0.0 \
  --disable-multi-arch \
  --enable-obsolete-rpc \
  --with-binutils=$(PREFIX)/bin \
  --with-headers=$(SYSROOT)/usr/include \
  --with-sysroot=$(SYSROOT)

最後に glibc を動的リンク可能な gcc は、

gcc 2回目の configure

./configure \
  --target=$(CROSS_ARCH) \
  --prefix=$(PREFIX) \
  --enable-languages=c,c++,fortran \
  --enable-libatomic \
  --disable-libitm \
  --enable-libgomp \
  --enable-libmudflap \
  --enable-libquadmath \
  --disable-libsanitizer \
  --enable-libssp \
  --enable-libstdcxx-pch \
  --enable-long-long \
  --enable-lto \
  --disable-multiarch \
  --disable-multilib \
  --enable-nls \
  --enable-plugin \
  --enable-shared \
  --enable-threads=posix \
  --enable-__cxa_atexit \
  --with-local-prefix=$(SYSROOT)/usr \
  --with-build-sysroot=$(SYSROOT) \
  --with-sysroot=$(SYSROOT) \
  --with-native-system-header-dir=/usr/include

この設定が正しいかどうか確証は持てませんが、printf を呼び出す C ソースコードをエラーなくビルド可能なコンパイラが作成できるので、良しとします。

引っかかったポイント

色々引っかかったのですが、覚えている限りのエラーと自分が取った対策を列挙しておきます。

どのバージョンのライブラリを組み合わせれば良いかわからない
私は Debian などの既存 Linux ディストリビューションが採用しているバージョンを参考にしました。ホスト側のコンパイラのバージョンも影響するため、昔ビルドが通っていた組み合わせでもビルドが通らないことはあります。
AArch64 に変えると glibc ビルドエラー
エラーの内容は redefinition of 'struct user_regs_struct でした。何それ……??と思いきや、sysroot にインストールした Linux カーネルヘッダが RISC-V 向けになっていた凡ミスでした。
glibc ビルドエラー
エラーの内容は enable-multi-arch support require gcc, assembler and linker indirect-function support でした。これは解決方法がわからんので、GCC の configure に --disable-multi-arch を指定し、回避しています。
gcc ビルドエラー
エラーの内容は Pthreads are required to build libgomp でした。これはややこしいので、別建てで書きます。

gcc ビルドエラー(詳細)

エラーメッセージだけ読むとさっぱりですが、config.log に記録されたテストプログラムとテスト結果によれば、pthread.h が見当たらないと言っているようです。

  • GCC の configure に --enable-libgomp を指定したため、libgomp がビルドされている
  • libgomp は pthread.h が見つからないので Pthreads are required to build libgomp と文句を言っていた

もちろん GCC の前に glibc のクロスビルドに成功しているので、pthread.h は存在しているものの、

  • glibc のヘッダをインストールする場所を間違えていた
  • gcc の --with-native-system-header-dir に指定したパスが間違っていた

これらの原因によって、pthread.h が見えなくなっていたようです。

感想

ツールチェーン構築って大変です。実際に体験すると、crosstool-NG や buildroot のありがたさが身に沁みます。

編集者: すずき(更新: 2021年 5月 20日 16:20)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



こんてんつ

open/close wiki
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報