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

C++版のリファクタリング/高速化 #4

Merged
merged 19 commits into from
Jun 22, 2020

Conversation

wx257osn2
Copy link
Contributor

@wx257osn2 wx257osn2 commented Jun 21, 2020

C++がRustに負けたと聞いて

変更点

  • ベースバージョンをC++17に変更
    • std::string_view 使いたかったので
    • GNU拡張も消しました.VLAはC++の機能ではない.
  • コンパイラオプションを追加
    • できるだけ性能が出やすいように
  • コンパイラをClangに変更
    • 近年のClangの最適化は凄まじいものがある
    • 実際今回もGCCより速かったし,RustがLLVMに乗っかるならC++も乗っかりたい
  • 競プロ味を感じるコードを修正
    • グローバル変数は個人的には日頃全くと言っていいほど使いませんが,ひとまず放置しています
    • この変更,「個人の好み」ではなく明確に理由があって変更しているので以下に示します
      • using namespace std; ですが,これはADLによって想定と異なる関数が呼び出される危険性が非常に高く,「望んでADLさせたい場合」を除いて使うべきではないです(し,その場合も必要な関数だけ using すれば良い).今回だと(最終的には別名関数 stoi_unchecked としましたが) 41b10e7 のように「標準ライブラリの関数と同名の関数」を定義した時に意図せずこれが発生する(例えば自分の実装した stoi ではなく std::stoi が呼ばれてしまう)危険性があります(ADLの挙動を完全に理解していてそれでも using namespace std; したい,ということであればまぁご自由にしていただければと思います,完全理解者には敵わないので…).
        • それはそれとして 3e5dfe9 時点で stoi の呼び出しに std:: 付けてないのはミスです…
      • #include<bits/stdc++.h> ですが,これはlibstdc++の独自実装なので標準ライブラリを変更しにくくなります(移植性が悪い).今回は(libc++環境用意するのが面倒だったので)コンパイラのみの変更に留めましたが,今後libstdc++以外の標準ライブラリ(libc++やMSの実装など)を使いたくなった時にそのままではコンパイルが通らなくなります.この点では上述のGNU拡張の排除も同様の理由です(MSVCで確実にコンパイルが通らない)
  • std::mapstd::unordered_map に変更
    • なんでC++だけ赤黒木なんですか…?
  • 1行読むのに std::getline を使うように変更
  • std::string_view 向けに stoi を再実装 (stoi_unchecked)
    • 入力として int 型に収まる整数以外は来ないことを前提に実装してある(_unchecked な)ので,ちゃんと整数かどうかを解析する std::stoi に比べて脆弱な実装ですが…
  • stof100 関数の実装を高速化
  • いくつかの関数をinline化
  • あと無駄なコピーとかキャストを削減

実行結果

以下の環境で1回ずつ走らせました.

$ uname -a
Linux HOSTNAME 4.15.0-72-generic #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.3 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.3 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
$ cat /proc/cpuinfo | grep "model name"
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
model name      : AMD Ryzen 7 2700X Eight-Core Processor
$ clang++ --version
clang version 11.0.0 (http://github.com/llvm/llvm-project 3646ee503dfb8bd4e02294fc122a80b95900ca16)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /path/to
$ g++ --version
g++ (GCC) 11.0.0 20200622 (experimental)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ rustc --version
rustc 1.44.1 (c7087fe00 2020-06-17)

Rust(8763034):

  Time (mean ± σ):      1.451 s ±  0.008 s    [User: 1.435 s, System: 0.015 s]
  Range (min … max):    1.442 s …  1.462 s    10 runs

Rust(#6, 905642e):

  Time (mean ± σ):      1.429 s ±  0.010 s    [User: 1.410 s, System: 0.018 s]
  Range (min … max):    1.411 s …  1.440 s    10 runs

C++(8763034):

  Time (mean ± σ):      1.774 s ±  0.010 s    [User: 1.755 s, System: 0.018 s]
  Range (min … max):    1.755 s …  1.792 s    10 runs

C++(8b4338f):

  Time (mean ± σ):      1.417 s ±  0.013 s    [User: 1.393 s, System: 0.023 s]
  Range (min … max):    1.407 s …  1.450 s    10 runs

Rustに勝ちました. 多分これが一番速いと思います

@reki2000 reki2000 merged commit a30f4e2 into reki2000:master Jun 22, 2020
@wx257osn2 wx257osn2 deleted the speedup-cxx branch June 22, 2020 13:32
@reki2000
Copy link
Owner

丁寧な解説ありがとうございます!!!ほとんど別物になってしまいましたが、マトモなC++はこうあるべきという点、大変勉強になります。

@wx257osn2
Copy link
Contributor Author

一見すると変更量は多いのですが,実態としては殆どは std:: 付けたり const 付けたりしてるだけなので「ほとんど別物」ということはないと思います(dijkstraの実装とか弄ってないし)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants