yaneurao / YaneuraOu

YaneuraOu is the World's Strongest Shogi engine(AI player) , WCSC29 1st winner , educational and USI compliant engine.
GNU General Public License v3.0
525 stars 140 forks source link

Graviton2をARM NEON SIMD対応 #201

Closed quiver closed 3 years ago

quiver commented 3 years ago

200 がマージされましたが、PUSH後にARM/NEON 対応のリファクタをできそうなことに気づいたため、別途起票します。

※マージ済みのPRには再PUSHできないらい。

また、過去の PR(#76, #77) を見る限りお詳しそうなので、メンションさせてもらいます。

CC @mizar

1. extra/bitop.h の修正

200 のextra/bitop.h のエラー箇所前後を確認すると、Android 向けで ARM 向け分岐が存在します。

#elif defined(USE_NEON)
#include <arm_neon.h>
#include <mm_malloc.h> // for _mm_alloc()
#else
#if defined (__GNUC__) 
#include <mm_malloc.h> // for _mm_alloc()
#endif

ここでやりたいことは NEON SIMD 対応の判定かと思いますので g++/clang の定義済みマクロの __ARM_NEON に変更しました。

2. Makefile に Graviton 2 ターゲットを追加

Graviton2(ARM Neoverse N1)は Arm V8.2 に対応しています。

評価関数 NNUE が NEON SIMD 対応されているため、 Android向けビルドファイル(jni/Android.mk)の ARM 設定をまねて Makefile のターゲットに GRAVITON2 を追加してみました。

参考 : Android ARM 設定

ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
  CPPFLAGS += -DIS_64BIT -DUSE_NEON -mfpu=neon
  LOCAL_ARM_NEON := true
endif

ifeq ($(TARGET_ARCH_ABI),x86_64)
  CPPFLAGS += -DIS_64BIT -DUSE_SSE42 -msse4.2
endif

ifeq ($(TARGET_ARCH_ABI),x86)
  CPPFLAGS += -DNO_SSE
endif

ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
  CPPFLAGS += -DUSE_NEON -mfpu=neon
  LOCAL_ARM_NEON := true
endif

結果、 NPS は 137493 から 455434 へと3倍になりました。

===========================
Total time (ms) : 60004
Nodes searched  : 27327920
Nodes/second    : 455434

このあたりを読む限り、NEON 対応していない SoC は極めてレアのようなので、より広く ARM ターゲットにしたほうが良いかもと、PUSH したあとで気づきました。

最近のArm(ちょっと主語がでかい)にはだいたいNEONが付いています。Raspberry Pi 2以降発売されたLinuxが動くSBCでは、NEON無しというSoCにはまずお目にかかれません。

USE_NEON 定義について

@mizar

jni/Android.mk では、ユーザー定義の USE_NEON を明示的に渡し、コード内で分岐しています。

Linux/Graviton2 環境では、1つ目の修正のように コード内の USE_NEON を 定義済みマクロの __ARM_NEON に置き換えても動作しました。

コード管理の観点では、__ARM_NEON に寄せたほうが楽と思うのですが Android 向けでは IS_NEON を使わないといけない理由があるのでしょうか?

取り急ぎ、1つ目と2つ目を反映したものを PUSH します。

yaneurao commented 3 years ago

おお!!! またまたありがとうございます!!!