ループの後ろで変数を宣言するのか、ループの中で宣言するのか? - ページ 11

 
Vict:

調べてみると、https://en.cppreference.com/w/cpp/compiler_support のコンパイラがモジュールを完成させていないので、見るべきものがないことが判明しました。

それでも clang 経由でモジュールを使用することができました

// module
export module M;
export int f(int x) {
    return 2 + x;
}

// main.cc
import M;
int main() {
        for(int i = 0;  i < 1000000;  ++ i)
                f(5);
}

最適化付きでコンパイルした場合、ループは全く実行されませんでした(つまり、最適化は、以前のように1つの翻訳ユニットだけでなく、翻訳ユニット+ハーフコネクションモジュール間で行われます)。LTOは一切なし。std c++がモジュールに完全に移行すれば、「この人工的なループの例では、なぜこんなに遅いのか」という疑問はなくなるはずです。

 
Alexey Navoykov:

ということで、今回のケースでも毎回メモリを確保し、削除していることがわかったようです。


ちなみに、前回は間違った結果を出してしまったかもしれません。 x86モードだった可能性が高いです。現在、x64モードでテストしていますが、C++による結果はずっと良くなっています。

1)〜2000msec

2)~200ms(3倍速になります)。

Studioも最新版に更新しましたが、x86でも以前のテストより速くなったので、その影響もあるのでしょう。

さて、C++はSharpに負けるほど恥ずかしくはない。)

うーん、ガベージコレクタがないわけですが、定義の問題は何なんでしょう?

速さではなく、メモリの話です
 
Alexey Navoykov 、constexpr string と vector が c++20 に引きずり込まれたことが判明しました。すなわち、私たちのすべてのテストは、文字列を提供するために、例えば、メモリを確保するなど、1つの命令を全く必要としない。(まあ、もちろん早い時期から記号が出なければの話ですが)。かっこいい。
 
Vict:
Alexey Navoykov 、constexpr string と vector が C++20 に引きずり込まれたことが判明しました。すなわち、これらのテストはすべて、メモリの確保など、文字列のメンテナンスのために1つの命令を全く必要としない。(まあ、もちろん早い時期から記号が出なければの話ですが)。かっこいい。

では、すべてを明示的にconstexprとしてマークする必要があるのでしょうか、それとも自動的に検出するのでしょうか?

やはり、規格の問題ではなく、コンパイラの問題なのでしょうか。 今は、不要なものを削ることができないのでしょうか。 特に、シャープのコンパイラは普通に最適化できるのに、同じマイクロソフトの プラス版が失敗するのは不思議です。 このような構文の最適化という意味では、共通のベースを持っているはずですが。

 
Alexey Navoykov:

すべて明示的にconstexprとしてマークする必要があるのか、それとも自動的に検出されるのか?

stdは自動で、コンパイル時に分かっている文字列を取得すれば十分です。この文字列を使ったすべての操作(検索、置換、...)は、コンパイル時に同じになります(sharpとmclもコンパイル時に我々の例をカウントしていると思われます)。すべてのコンテナをconstepxrにする予定です。つまり、もうコンパイラの気分には左右されないが、標準では保証されているので、例えば文字列解析でテンプレート・パラメータを計算することができるのだ。ここで興味深いのは、new/deleteがconstexpr(constexpr型の場合)にも対応するようになったことです。

やはり、規格の問題ではなく、コンパイラの問題なのでしょうか。 何か、不要なものをカットできないようになっているのでしょうか。 特に、シャープのコンパイラは普通に最適化できているのに、同じマイクロソフトの プラス版では失敗するというのは、(こうした構成の最適化という点では)共通基盤があるように思えますが、不思議です

Plusは、最適化の可能性という点では、(LTOを使わない場合)1つの翻訳単位の中だけというデメリットがあります。もちろん、ヘッダーファイルでstdを全て行うことも可能ですが、彼らはそうしません(コンパイル時のため?)この点では、モジュールを搭載したシャープの方が進んでいます。しかし、c++20では、モジュールの登場により、これもすぐに解決されるでしょう。また、stdをそこに移動させる計画もある(まずモジュールをデバッグし、それから書くそうです)。しかし、VSは既にstd on modulesをやっているようなので、試してみてはいかがでしょうか(上記リンク先を参照)。

しかし、私は、ループの後で宣言する方が良いと思います。

 
Alexey Navoykov:

興味本位でC#でもテストしてみることにした。 結果は速度がほぼ同じなだけでなく、C++よりもはるかに高速に動作することがわかった。

結果

総和:894782460、時間:69ms。

総和:894782460、時間:56ms

そして、ここにC++でのアナログがある。

総和:894782460、時間:2947ms

総和:894782460、時間:684ms

VS 2019でテストしています。すべての最適化が有効になって います。

そんなC++のプログラムをねじ込む)。

p.s. C# での結果はテストによって大きく異なりますが、平均してどちらのバージョンも同じように高速です。

ヒント:シャープでは文字列が基本型、プラスではプラスで書かれたクラスです。Sharpe 変数では文字列の割り当てが1回、プラスでは10e6回行われる。結局、プラスは速いのですが、ボーイングのインド人のようにハンパなものを作らず、コードを書くときに頭を使う必要があります。
 
SeriousRacoon:
ヒント:シャープでは文字列が基本型、プラスではプラスで書かれたクラスです。Sharpe 変数では文字列の割り当てが1回、プラスでは10e6回行われる。プラスアルファは結局は早いのですが、ボーイングのインディアンのように猫背にするのではなく、コードを書くときに脳をオンにする必要があります。
いや、そういうことではないんです。私は単に、文字列にはクラスがあり、割り当てられるのは参照であって、オブジェクトそのものではないことを忘れていました。 ですから、この形式での比較は正しくありません。
 

ところで、最適化といえば。ここでコンパイラに何か最適化させたいのでしょうか?

mutex mtx;

void thread_0() {
        while (true) {
                do_task_0();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_1();
                }
                do_task_2();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_3();
                }
                do_task_4();
        {
}
void thread_1() {
        while (true) {
                do_task_5();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_6();
                }
                do_task_7();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_8();
                }
                do_task_9();
        {
}
 
Alexey Navoykov:
いや、そこではポイントがまったく違う。ただ、そこでstringがクラスであることを忘れていて、代入されるのは参照であって、オブジェクトそのものではないのです。 ですから、この形の比較は不正確です。
参照(ポインタ)はどこに割り当てられているのですか? プラスクラスの文字列の中ですか? バッファの選択とコピーがそこで行われるとはどういうことですか?
 
SeriousRacoon:
参照(ポインタ)はどこに割り当てられているのですか? プラスクラスの文字列の中ですか? どういうことですか、バッファの選択とコピーです。

口が減らない