Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

動作を高速化する #85

Open
kamiyaowl opened this issue Sep 23, 2019 · 33 comments
Open

動作を高速化する #85

kamiyaowl opened this issue Sep 23, 2019 · 33 comments
Assignees
Labels
embedded emulator for embedded enhancement New feature or request environment build system, test system, other

Comments

@kamiyaowl
Copy link
Owner

思い当たる節

@kamiyaowl kamiyaowl added enhancement New feature or request environment build system, test system, other embedded emulator for embedded labels Sep 23, 2019
@kamiyaowl kamiyaowl self-assigned this Sep 23, 2019
@kamiyaowl
Copy link
Owner Author

FPSカウンターだけの表示だと秒10000いける

    for (uint32_t counter = 0 ; ; ++counter ) {
        // EmbeddedEmulator_update_screen(&fb);
        // print_framebuffer(150, 0, 2);

        sprintf(msg, "%d", counter);
        BSP_LCD_DisplayStringAt(5, 5, (uint8_t *)msg, LEFT_MODE);

        /* Touchscreen test */
        // TS_StateTypeDef  TS_State = {0};
        // BSP_TS_GetState(&TS_State);
        // if(TS_State.touchDetected) {
        //     const uint16_t x1 = TS_State.touchX[0];
        //     const uint16_t y1 = TS_State.touchY[0];
        //     BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
        //     BSP_LCD_FillCircle(x1, y1, 10);
        // }
    }

@kamiyaowl
Copy link
Owner Author

エミュレーションだけ入れると10fps

    for (uint32_t counter = 0 ; ; ++counter ) {
        EmbeddedEmulator_update_screen(&fb);
        // print_framebuffer(150, 0, 2);

        sprintf(msg, "%d", counter);
        BSP_LCD_DisplayStringAt(5, 5, (uint8_t *)msg, LEFT_MODE);

        /* Touchscreen test */
        // TS_StateTypeDef  TS_State = {0};
        // BSP_TS_GetState(&TS_State);
        // if(TS_State.touchDetected) {
        //     const uint16_t x1 = TS_State.touchX[0];
        //     const uint16_t y1 = TS_State.touchY[0];
        //     BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
        //     BSP_LCD_FillCircle(x1, y1, 10);
        // }
    }

@kamiyaowl
Copy link
Owner Author

print_framebuffer入れても8fps、これは最適化が効いている気がする

    for (uint32_t counter = 0 ; ; ++counter ) {
        EmbeddedEmulator_update_screen(&fb);
        print_framebuffer(150, 0, 2);

        sprintf(msg, "%d", counter);
        BSP_LCD_DisplayStringAt(5, 5, (uint8_t *)msg, LEFT_MODE);

        /* Touchscreen test */
        // TS_StateTypeDef  TS_State = {0};
        // BSP_TS_GetState(&TS_State);
        // if(TS_State.touchDetected) {
        //     const uint16_t x1 = TS_State.touchX[0];
        //     const uint16_t y1 = TS_State.touchY[0];
        //     BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
        //     BSP_LCD_FillCircle(x1, y1, 10);
        // }
    }

@kamiyaowl
Copy link
Owner Author

ざっとこんな感じ。本当ならPPUは完全並列で動かしていいのだけれど、ポリシーに反するのでアレ

  • Emulateが異様に遅い 80ms
  • print_framebuffer 10ms
  • print fpscounter <5ms

kamiyaowl added a commit that referenced this issue Sep 23, 2019
@kamiyaowl
Copy link
Owner Author

opt-level=3, debug_assertions=noで2msぐらい削れた

@kamiyaowl
Copy link
Owner Author

ICache/DCache有効にしてなさそう。core_cm7のSCB_xxxにキャッシュ操作周りのインライン関数がある

@kamiyaowl
Copy link
Owner Author

体感でわからんぐらいだな、なんかミスってるかも

    SCB_EnableDCache();
    SCB_EnableICache();

@kamiyaowl
Copy link
Owner Author

ART, Prefetch Buffer有効化して9fpsぐらい。framebuffer解決しても15fps届くかどうかぐらいか

kamiyaowl added a commit that referenced this issue Sep 23, 2019
kamiyaowl added a commit that referenced this issue Sep 23, 2019
@kamiyaowl
Copy link
Owner Author

思い当たる節

  • rust 配列境界チェック
  • rust arm向けバイナリのusizeの扱い
  • rust u16命令の扱い(可能ならu32で揃えたほうが良さげかも)
  • rust コールスタック積むオーバーヘッド
  • rust 乗算、除算系
  • rust ppu周りで同様の計算を毎pixelごとやっている可能性

@kamiyaowl
Copy link
Owner Author

一旦デスクトップ向け環境でもいいから、ベンチ図る環境を構築すべき、100frame書くまでにどのぐらいかかるか。などで

@kamiyaowl
Copy link
Owner Author

u16のアンアラインドな読み書きは間違いなくパフォーマンス低下になっていそう

@kamiyaowl
Copy link
Owner Author

まぁあえてu32使わせるのももとのコード崩しすぎるから微妙。
あとppuのdraw_lineは剰余が使われていたりするので、ここもdisasm眺めてみたほうがいいかも

@kamiyaowl
Copy link
Owner Author

  • TCMを使う

@kamiyaowl
Copy link
Owner Author

SRAM先頭はDTCMに乗ってるけど、FlashはITCM使ってなさそう
実際のところ、ROMの固定地はcassette構造体の配列にコピーして利用しているのでFlashのアクセス経路には依存しない
DCacheを有効にしてもすでにDTCM上にあるので、ゼロウェイト非キャッシュで恩恵がなかったと見るべき

MEMORY

{ 

FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K

RAM (rwx) : ORIGIN = 0x200001F8, LENGTH = 512K - 0x1F8

}


@kamiyaowl
Copy link
Owner Author

https://youtu.be/73ciNT9tl-U
f4で30fps前後は出ていそう

@kamiyaowl
Copy link
Owner Author

小手先の修正で劇的に速くならなかったので、以下案

mbedプラットフォーム上でブラッシュアップするもの

  • Cache有効化
  • fbのDMA転送

処理としてブラッシュアップできる物

  • cpuの処理最適化(あまりなさそう)
  • ppuの最適化
    • 水平アドレスの再計算周り(インクリメントで済む部分などはあるはず)
    • ベースアドレスの計算結果保持(scroll regがあるので保持は難しそう)
    • パレット参照など、データを複数回参照で求めている場合の保持
  • 割り算、剰余の削減

rustとしてunsafeを伴うが高速化できるもの

  • 配列境界チェックの無効化
  • const fnなどの導入

arm向けに最適化するもの

既存のコードと整合取れなくなる点どうしよう...型まるごと置き換えたりすると原型は保てなさそう

  • 関数呼び出しの引数が4以下になるようにする
    • スタック渡し対策
  • u8, u16の使用をやめる
    • データサイズ変換対策
    • usizeの扱い(わからん)

@kamiyaowl
Copy link
Owner Author

現在、ベンチテストは60frame書くのにかかる時間

running 6 tests
test tests::test_run_hello_cpu ... ignored
test tests::test_run_hello_ppu ... ignored
test tests::test_run_mario_demo ... ignored
test tests::test_run_mario_title ... ignored
test tests::test_run_nestest ... ignored
test bench::bench_hello ... bench:  94,229,800 ns/iter (+/- 4,619,103)

kamiyaowl added a commit that referenced this issue Sep 24, 2019
@kamiyaowl
Copy link
Owner Author

ちょっと変わった...?

test bench::bench_hello ... bench:  92,228,830 ns/iter (+/- 7,182,915)    
test bench::bench_hello ... bench:  93,150,040 ns/iter (+/- 5,742,562)

@kamiyaowl
Copy link
Owner Author

剰余をbit andにするのはあまり変わらなそう

@kamiyaowl
Copy link
Owner Author

関数呼び出しをフェッチしてあげるのは結構明確に聞くっぽい、何でもかんでもinlineにするのはきらいだが

test bench::bench_hello ... bench:  89,489,360 ns/iter (+/- 7,959,146)

kamiyaowl added a commit that referenced this issue Sep 24, 2019
@kamiyaowl
Copy link
Owner Author

これみてたらやっぱunstable使ってでもconst fn使ったほうがいい気がしてきた

test bench::bench_hello ... bench:  76,373,280 ns/iter (+/- 3,452,911)

kamiyaowl added a commit that referenced this issue Sep 24, 2019
@kamiyaowl
Copy link
Owner Author

更に引数の数を減らしたりして2ms縮めた。多分これはarm相手だともっと効くはず。

test bench::bench_hello ... bench:  74,050,190 ns/iter (+/- 2,112,266)

動かしてみた感じ、体感でわかるぐらい気持ち早くなっていたがまだまだ

kamiyaowl added a commit that referenced this issue Sep 24, 2019
@kamiyaowl
Copy link
Owner Author

kamiyaowl commented Sep 24, 2019

進捗

mbedプラットフォーム上でブラッシュアップするもの

処理としてブラッシュアップできる物

  • cpuの処理最適化(あまりなさそう)
  • ppuの最適化
    • 水平アドレスの再計算周り(インクリメントで済む部分などはあるはず)
    • ベースアドレスの計算結果保持(scroll regがあるので保持は難しそう)
    • パレット参照など、データを複数回参照で求めている場合の保持
  • 割り算、剰余の削減

94.2ms -> 74.1msまで縮んだよ。やったね!

rustとしてunsafeを伴うが高速化できるもの

  • 配列境界チェックの無効化
  • const fnなどの導入

arm向けに最適化するもの

既存のコードと整合取れなくなる点どうしよう...型まるごと置き換えたりすると原型は保てなさそう

  • 関数呼び出しの引数が4以下になるようにする
    • スタック渡し対策
  • u8, u16の使用をやめる
    • データサイズ変換対策
    • usizeの扱い(わからん)

@kamiyaowl
Copy link
Owner Author

コードぶっ壊したくないとの兼ね合いが難しいしつらい。特にrustだと

@kamiyaowl
Copy link
Owner Author

境界チェック外しは、featureでマクロ切り替える方式が良さそう

@kamiyaowl
Copy link
Owner Author

あとusizeはターゲットのアドレス空間でサイズが決まる模様。arm向けなら4byte

@kamiyaowl
Copy link
Owner Author

カセットの読み書きをuncheckedにしたら1ms縮まった...

test bench::bench_hello ... bench:  73,403,310 ns/iter (+/- 2,966,874)

@kamiyaowl
Copy link
Owner Author

system/video_systemに適用したがあまり変わらず、全体的なアクセスはカセットを占めているので自明ではある。

@kamiyaowl
Copy link
Owner Author

test bench::bench_hello ... bench:  73,348,660 ns/iter (+/- 1,937,178)

@kamiyaowl
Copy link
Owner Author

きちんと確認していないけど条件的に範囲外例外を超えない可能性が高い領域だからかもしれない。
system_read/writeの中身はリージョンサイズで小さい順にifで引っ掛けているので、コンパイラが最後の条件までは範囲外にならないことを知っている。
なのでカセットに対してしか有効な高速化にならなかった。

@kamiyaowl
Copy link
Owner Author

system_ppu_regにinlineいれても早くならんな

@kamiyaowl
Copy link
Owner Author

x86だからかと思ったけど普通に遅くなった

@kamiyaowl
Copy link
Owner Author

(ARMでも

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
embedded emulator for embedded enhancement New feature or request environment build system, test system, other
Projects
None yet
Development

No branches or pull requests

1 participant