コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2023年7月20日 >>> 2023年7月11日
link もっと後

2023年7月20日

RISC-Vも完璧じゃない

目次: RISC-V

RISC-Vは最後発の命令セットだけあって、従来の命令セットで評判の悪かった部分は改善されている場合が多いです。しかし人の作るものですからミスや見落としはあります。

例としてわかりやすいのがRV64I命令セットの32bit unsignedと64bit unsigned加算処理です。下記のようなコードを書いたとします。

32bit unsignedと64bit unsigned加算処理のサンプルコード

unsigned int __attribute__((noinline)) something(int n)
{
	return n * n;
}

int test(unsigned int num)
{
	unsigned long long sum = 0;

	for (int i = 0; i < num; i++) {
		sum += something(i);    //32bit unsigned + 64bit unsigned
	}

	return sum;
}

下記のようにコンパイルします。RV64GCはRV64IMAFDCの略(M: Multiplication and Division, A: Atomic, F: Single-Precision Floating-Point, D: Double-Precision Floating-Point, C: Compressed)です。RV64I以外のMAFDCの各命令も出てきますが、話題と関係ないので気にしないでください。RV64GCが基本的な命令セットくらいの認識でOKです。

RV64GCでコンパイル
$ riscv64-unknown-elf-gcc -g -O2 -march=rv64gc -mabi=lp64d -c -o rv64gc.o a.c

逆アセンブルを見ると変なシフト命令(アドレス24, 26)が2つ出力されます。

RV64GCを使用したときの逆アセンブル

000000000000001a <.L5>:
                sum += something(i);
  1a:   8522                    mv      a0,s0         # s0: i, s1: sum
  1c:   00000097                auipc   ra,0x0
  20:   000080e7                jalr    ra            # call something()
  24:   1502                    slli    a0,a0,0x20    # a0: something() の返り値
  26:   9101                    srli    a0,a0,0x20    # shift x 2で上位32ビットを0埋め
        for (int i = 0; i < num; i++) {
  28:   2405                    addiw   s0,s0,1
                sum += something(i);
  2a:   94aa                    add     s1,s1,a0      # shift x 2 + add
        for (int i = 0; i < num; i++) {
  2c:   ff2417e3                bne     s0,s2,1a <.L5>

RV64Iには32bit unsigned向けの加算命令がなく、32bit unsignedを64bit unsignedにゼロ拡張してから加算する必要があるためです。さらに悲しいことにゼロ拡張する命令もなく、32bit左シフト命令+32bit右論理シフト命令でゼロ拡張するヘボい処理になります。

SiFiveあなたもか

シフト命令2つくらい何だというのか?ケチケチするなよ?という感覚が普通かもしれませんが、余計な命令が出ると特にローエンドのCPUでは性能への影響が無視できません。どうやらCoreMarkのような典型的なベンチマークにも影響が出ていたようで、

SiFiveが公開しているCoreMarkの型定義(一部抜粋)

// GitHub: sifive/benchmark-coremark
// freedom-metal/core_portme.h

typedef signed short ee_s16;
typedef unsigned short ee_u16;
typedef signed int ee_s32;
typedef double ee_f32;
typedef unsigned char ee_u8;
typedef signed int ee_u32;     //★★★u32なのに "signed" intになっている★★★
typedef signed long ee_u64;    //★★★u64なのに "signed" longになっている★★★
#if __riscv_xlen == 32
typedef ee_u32 ee_ptr_int;
#else
typedef ee_u64 ee_ptr_int;
#endif
typedef signed int ee_size_t;

RISC-Vの盟主たるSiFiveすらも「unsigned型をsigned型にすりかえて性能を上げるぞい!」というCoreMarkハックを行っていた(該当箇所へのリンク)ほどです……。

RISC-Vパッチワーク

当然RV64Iのまずい点はRISC-Vの方々も気づいており、B拡張(Bit-manipulation extensions)を追加したときに上記の問題は修正されました(RISC-V Bitmanipulation extension規格書へのリンク)。

B拡張はZba, Zbb, Zbc, Zbsの4つがあります。

  • Zba: Address generation instructions
  • Zbb: Basic bit-manipulation
  • Zbc: Carry-less multiplication
  • Zbs: Single-bit instructions

この中のZba拡張にて32bit unsigned加算命令であるadd.uw命令が追加されました。他にも1, 2, 3bitシフト&加算命令なんかも追加されています。unsigned加算や1, 2, 3bitシフト&加算は配列の要素のアドレスを計算する際に頻出で、Address generation instructionsというグループ名にしたのでしょう。

Zba拡張を使うとどのように改善されるか確認します。

RV64GCとZba拡張でコンパイル
$ riscv64-unknown-elf-gcc -g -O2 -march=rv64gc_zba -mabi=lp64d -c -o rv64gcb.o a.c

逆アセンブルを見ると変なシフト命令は消滅し、新たにadd.uw命令が出力されていることが分かると思います。

RV64GCとZba拡張を使用したときの逆アセンブル結果

000000000000001a <.L5>:
                sum += something(i);
  1a:   8522                    mv      a0,s0       # s0: i, s1: sum
  1c:   00000097                auipc   ra,0x0
  20:   000080e7                jalr    ra          # call something()
        for (int i = 0; i < num; i++) {
  24:   2405                    addiw   s0,s0,1
                sum += something(i);
  26:   089504bb                add.uw  s1,a0,s1    # shift x 2は消滅、add.uwのみ
        for (int i = 0; i < num; i++) {
  2a:   ff2418e3                bne     s0,s2,1a <.L5>

めでたしめでたし。なんですけど、人によっては色々言いたいこともあると思います。Bit-manipulationとAddress generation全然関係ないぞ?とかね。

しかし冒頭にも書いたとおり、何事も最初から完璧なものはないです。命令セットが汚くなっていくのはRISC-Vが実用段階に入った証であり、むしろ良いことだと個人的には思います。

編集者:すずき(2023/07/23 17:11)

コメント一覧

  • hdkさん(2023/07/21 22:45)
    x86脳なので、mov %eax,%eax (32ビット→ゼロ拡張64ビット) とか、movzwl %ax,%eax (16ビット→ゼロ拡張32ビット) とか、そういうのに相当する何かがありそうに思ってしまいますが、わざわざシフト命令2個生成されるところをみると、ないんですね... intとintptr_tのサイズが同じならよかったんでしょうけど、違うと確かに厳しそう...
  • すずきさん(2023/07/23 17:10)
    x86はもちろん、先代であるMIPSにさえこの手のミスはないらしい(詳しくは知らない)んですが、RISC-Vは命令削減にこだわり過ぎたのか、見落としたのかなんだか知らんのですが、ミスってるんですよねー……。
open/close この記事にコメントする



2023年7月14日

AndesのCPUコアが搭載されたRISC-V SoCボードを購入

目次: RISC-V

先日6月14日に発売開始されたRenesas RZ/Five(R9A07G043F01GBG)搭載のボードAP-RZFV-0A製品紹介サイトへのリンク)を購入しました。

SoCはRenesas製で、CPUコアは台湾Andes TechnologyのAX45MP(製品紹介サイトへのリンク)です。

追加部品を購入

ボードだけ購入するとACアダプタが付属していません。全部入りが良ければLinux開発キットを併せて購入すると良いかと思います。

秋月にて5VセンタープラスのACアダプタATS012S-W050U(製品紹介サイトへのリンク)を購入しました。700円です。安い。何も考えず2A出力のアダプタにしましたが、出力が足りなかったらまた考えます。

ボード上のJTAG端子CN3を見ると、ハーフピッチと呼ばれる1.27mm間隔の10ピンヘッダでした。このヘッダに接続できるJTAGケーブルを持っていないので、Strawberry LinuxにてJTAG変換基盤ARM-JTAG-20-10(製品紹介サイトへのリンク)を購入しました。800円くらいです。これも安い。

電源に関してはACアダプタ以外にも、安定化電源やUSBから取る方法(ジャンパ端子J18を半田付けでショートさせる必要あり)があります。ボードのマニュアルをご参照ください。

JTAGを繋ぐ

JTAGコネクタCN3にJTAG変換基盤ARM-JTAG-20-10のハーフピッチコネクタを接続します。ケーブルの赤い線が1番ピン側(ボード上の白い三角マークがある、LANコネクタなどがある方)です。写真も載せておきます。


AP-RZFV-0A CN3にJTAGケーブルを接続

ボードのマニュアルを見るとわかりますが、SoCにDEBUGENという端子があり [1]DebugModeと [0]NormalMode(出荷時設定)があるそうです。ボード上のDIPスイッチ(SW2の3番)をOFFにするとDebugModeに切り替わりJTAGが繋がるようになります。

OpenOCDにて接続

お持ちのJTAGによって設定がやや違いますが、SEGGER J-Linkの場合はOpenOCDの設定ファイルはこんな感じです。

OpenOCD設定ファイルfor RZ/Five
adapter speed 1000
reset_config trst_and_srst
 
set _CHIPNAME riscv
set _DAP_TAPID 0x1000563d
 
jtag newtap $_CHIPNAME dap -irlen 5 -ircapture 0x01 -irmask 0x03 \
        -expected-id $_DAP_TAPID
 
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 riscv -chain-position $_CHIPNAME.dap -coreid 0

設定をファイルに保存したら、J-Linkの設定ファイルとともに指定して起動しましょう。

OpenOCD起動ログ
$ sudo ./src/openocd -c 'bindto 0.0.0.0' -f tcl/interface/jlink.cfg -f ~/openocd_renesas_rzv.cfg

Open On-Chip Debugger 0.11.0+dev-00551-gaad871805 (2022-01-16-22:30)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
0
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : J-Link V11 compiled Jul  3 2020 10:47:34
Info : Hardware version: 11.00
Info : VTarget = 1.812 V
Info : clock speed 1000 kHz
Info : JTAG tap: riscv.dap tap/device found: 0x1000563d (mfg: 0x31e (Andes Technology Corporation), part: 0x0005, ver: 0x1)
Info : datacount=4 progbufsize=8
Info : Examined RISC-V core; found 1 harts
Info :  hart 0: XLEN=64, misa=0x800000000094312d
Info : starting gdb server for riscv.cpu.0 on 3333
Info : Listening on port 3333 for gdb connections

無事CPUが認識されました。よきかなよきかな。

編集者:すずき(2023/07/19 08:54)

コメント一覧

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



2023年7月13日

PHP 8への道のり

目次: 自宅サーバー

この日記システムをPHPの最新バージョンPHP 8に対応させました。

きっかけはさくらインターネットから「PHP 5を使うのは危険だよ」というメールが来たことです。PHP 5.6のEOLは2018年なので5年くらい放置していたんですね。さすがにサボりすぎました。

PHP 5とPHP 7は互換性が保たれていて(PHP 6は欠番らしい)おり1文字も変更することなくPHPのバージョンアップに対応できました。ところがPHP 8は古い機能を色々と廃止したようで全く動きませんでした。

PHP 8で動かなくなった機能達

PHP 8で動かなくなった機能達のエラーメッセージや直し方(正しいかどうか知らない)を順不同で紹介したいと思います。

get_magic_quotes_gpc() 関数は廃止
PHP Fatal error:  Uncaught Error: Call to undefined function get_magic_quotes_gpc()

この関数は説明を見ても常にfalseを返すと書いてあり、もはや存在しようがしなかろうが呼ぶ意味がありません。この関数を呼んでいるコードごと消しました。

クラスのコンストラクタが曲者でした。PHP 7までクラスと同名の関数がコンストラクタ扱いされましたが、PHP 8から __construct() がコンストラクタ扱いされます。この変更の影響であらゆるクラスの初期化が実行されなくなって、訳のわからないエラーを引き起こしました。デバッグが一番面倒くさかったです。

波括弧のオフセット指定は廃止
PHP Fatal error:  Array and string offset access syntax with curly braces is no longer supported

PHP 8では波括弧 {} によるオフセットの指定が廃止されたので、角括弧 [] に置き換える必要があります。難しくはないですが、地味に使っている箇所が多く修正が大変でした……。

each() 関数は廃止
PHP Fatal error:  Uncaught Error: Call to undefined function each()

PHP 8ではeach() 関数が廃止されました。これも複数ヶ所で使っていて修正が面倒でした。

修正例

// 修正前
reset($array);
list($a, $b) = each($array);

// 修正後
reset($array);
$a = key($array);
$b = current($array);

上記のように先頭のキーと値を取り出すためだけに使っていたので、単純にkey() とcurrent() 関数で書き換えました。

mb_strrpos() の引数
PHP Fatal error:  Uncaught TypeError: mb_strrpos(): Argument #3 ($offset) must be of type int, string given

PHP 7はmb_strrpos() 関数の3番目の引数(offsetの位置)にencodeを指定してもエラーにならなかったのですが、PHP 8ではoffset, encodeを指定しないとエラーになるようです。PHPは良くわかりませんなあ。

編集者:すずき(2024/01/13 14:29)

コメント一覧

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



2023年7月12日

自宅のサーバーとPHP

目次: 自宅サーバー

自宅のファイルサーバー兼WebサーバーでPHPが動かなくなっていました。

素のPHP 8すら動かないので、おそらくPHP 5の寿命が尽きたときにPHP周りの設定が全部吹っ飛んで動かなくなったと思われます。自宅のWebサーバーは自宅から見えないので、長らく気づいていませんでした……。あれまあ。

まずはPHP CGIや日記システムで使っているGDやmbstringをインストールします。

PHPのインストール
# apt-get install php-cgi php-gd libapache2-mod-php8.2 php8.2-mbstring

Apache 2の設定ファイルを変更してPHP 8.2を有効にします。

Apache 2でPHP 8.2を有効にする
# cd /etc/apache2/mods-enabled
# ln -s ../mods-available/php8.2.conf
# ln -s ../mods-available/php8.2.load

# systemctl restart apache2

Apache 2はユーザーディレクトリといって /home/username/public_html/ ディレクトリに置いたファイルが、URL /~username/ で見える仕組みがありまして、日記システムはユーザーディレクトリに配置しています。

初期状態のphp8.2.confだとユーザーディレクトリの配下にあるPHPスクリプトは動きません。わざと無効化してあります。

php 8.2のユーザーディレクトリの設定

# /etc/apache2/mods-enabled/php8.2.conf

#...略...

# Running PHP scripts in user directories is disabled by default
#
# To re-enable PHP in user directories comment the following lines
# (from <IfModule ...> to </IfModule>.) Do NOT set it to On as it
# prevents .htaccess files from disabling it.
<IfModule mod_userdir.c>
    <Directory /home/*/public_html>
        php_admin_flag engine Off
    </Directory>
</IfModule>

コメントにある通りIfModuleタグごと全てコメントにして、Apache 2を再起動しましょう。これできっとPHP 8が動くはずです。

編集者:すずき(2024/01/13 14:29)

コメント一覧

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



link もっと前
2023年7月20日 >>> 2023年7月11日
link もっと後

管理用メニュー

link 記事を新規作成

<2023>
<<<07>>>
------1
2345678
9101112131415
16171819202122
23242526272829
3031-----

最近のコメント5件

  • link 24年4月22日
    hdkさん (04/24 08:36)
    「うちのHHFZ4310は15年突破しまし...」
  • link 24年4月22日
    すずきさん (04/24 00:37)
    「ちゃんと数えてないですけど蛍光管が10年...」
  • link 24年4月22日
    hdkさん (04/23 20:52)
    「おお... うちのHHFZ4310より後...」
  • link 20年6月19日
    すずきさん (04/06 22:54)
    「ディレクトリを予め作成しておけば良いです...」
  • link 20年6月19日
    斎藤さん (04/06 16:25)
    「「Preferencesというメニューか...」

最近の記事3件

  • link 24年4月25日
    すずき (04/26 16:49)
    「[AVIFの変換] AVIFが読めないアプリケーションがたまにあるので、AVIF(AV1 Image File Format)...」
  • link 24年2月7日
    すずき (04/24 02:52)
    「[複数の音声ファイルのラウドネスを統一したい] PCやデジタル音楽プレーヤーで音楽を聞いていると、曲によって音量の大小が激しく...」
  • link 24年4月22日
    すずき (04/23 20:13)
    「[仕事部屋の照明が壊れた] いきなり仕事部屋のシーリングライトが消えました。蛍光管の寿命にしては去年(2022年10月19日の...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
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 2024年
open/close 過去日記について

その他の情報

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

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 04/26 16:49