new int[]とstd::vectorクラスでの実行速度差

<動作環境>

Intel MacBook Pro 16

 

<メモリ管理>

new int[]方式はメモリの領域管理、特にリリースを自分で管理しなければいけないのでバグの入り込み余地が多いのですが、コンテナクラスを使うことでその可能性を少なくしてくれます。しかし、想像するにパーフォーマンスは落ちるでしょう。ということで比べてみました。

#include <iostream>
#include <utility>
#include <vector>

const int a_size = 1000000*100;

class home
{
    int* m_land;
    int* cp_land;

public:
    explicit home(int size)
        : m_land{new int[size] ()}{}
    
    ~home() { delete [] m_land;}

    home(home&& other);

    int* land() const { return m_land; }

    int* land_cp() const { return cp_land; }

    void copy()
    {
        cp_land = new int[a_size];
        for (int i = 0; i <= a_size; i++)
        {
            cp_land[i] = m_land[i];
        }
    }

    void v_copy()
    {
        std::vector v_int(a_size, 0);
        //std::vector vc_int(a_size);
        //std::copy(v_int.begin(), v_int.end(), vc_int.begin());
        std::vector vc_int = v_int;
    }

    void del()
    {
        delete [] cp_land;
    }
};

home::home(home&& other)
    : m_land{other.m_land}
{
    other.m_land = nullptr;
}


int main()
{
    std::chrono::system_clock::time_point  start, end;
    start = std::chrono::system_clock::now();

    home A{a_size};
    std::cout << "A\'s land address : " << A.land() << std::endl;

    A.copy();
    std::cout << "A\'s cp_land address : " << A.land_cp() << std::endl;
    A.del();

    home B{std::move(A)};
    std::cout << "B\'s land address : " << B.land() << std::endl;

    B.v_copy();

    std::cout << std::endl;
    end = std::chrono::system_clock::now();
    double elapsed = std::chrono::duration_cast(end-start).count();
    std::cout << "elapsed time : " << elapsed << " ms" << std::endl;
}

追加したのはv_copyメソッドとその中でパターンの変更とcopyメソッド使う使わないはソース(35~38行目、69行目の該当行コメントアウト)で対応。

 

<実行結果>

① std::vectorで領域確保だけで2秒近く要している

② 領域のパディングは自動と明示である程度の差がある、new int[]は0でしかできないけど、vectorは任意の値で初期化できるのはアドバンテージ

③ コピーは単純コピーが相対的std::copyより早いけど、それでもマニュアルのforループコピーよりもおよそ2倍(std::copyはおよそ4倍)の時間が掛かる

④ std::copyは実行時間最遅

領域サイズ:100MB

<初期状態:マニュアル(new int[])で領域確保とコピー>
A's land address : 0x7fad25700000
A's cp_land address : 0x7fad05700000
B's land address : 0x7fad25700000

elapsed time : 497 ms


<領域確保:おそらく0埋めされるはず>
A's land address : 0x7f8996700000
A's cp_land address : 0x7f8976700000
B's land address : 0x7f8996700000

elapsed time : 2292 ms


<領域初期化値を明示的に追加>
A's land address : 0x7f8549700000
A's cp_land address : 0x7f8529700000
B's land address : 0x7f8549700000

elapsed time : 2518 ms


<別のstd::vectorにコピー>
A's land address : 0x7fc174f00000
A's cp_land address : 0x7fc154f00000
B's land address : 0x7fc174f00000

elapsed time : 3510 ms


<コピーにstd::copyを使用>
A's land address : 0x7f8b68700000
A's cp_land address : 0x7f8b48700000
B's land address : 0x7f8b68700000

elapsed time : 4396 ms


便利・セキュアさと処理時間は相反するというのは、まあそんなものでしょうか。

ソースは、

https://isehara-3lv.sakura.ne.jp/blog/2022/07/13/右辺値参照の代表的使い方である移譲処理でのパ/

の記事に追加して以下のurlになります。

https://github.com/chateight/c-plusplus/blob/master/move_perform.cpp

 

P.S. @2022/7/21

M1 MacBook Airで同じ処理実行させると処理速度が全く違う。いずれのケースでも1秒以下(700ms程度)で実行されるから、その差はなんだろう?

そのままのソースではコンパイルできないので、#include <chrono>は必要でしたが、それは本質ではない。

可能性としては、コンパイラーのバージョンぐらい(c++11 vs c++20)なのか?MacBook Pro 16のコンパイルオプションを-std=c++20にしても変わらないからそうじゃないよね。だとすると処理系の差?

 

admin

右辺値参照の代表的使い方である移譲処理でのパーフォーマンス効果

<実行環境>

Intel MacBook pro 16

 

<右辺値参照で移譲処理>

コピーは性能に大きな影響があるのは常ですが、じゃどれぐらい影響あるのか試してみました。

やってること、

① メモリ領域確保(初期化 or 未初期化:13行目の()有無)、この場合には100MB確保と領域の移譲処理

② 領域のコピー(有り or 無し:53/54/55行目のコメントアウト有無)

の4パターンの実行速度比較

#include <iostream>
#include <utility>

const long a_size = 1000000*100;

class home
{
    int* m_land;
    int* cp_land;

public:
    explicit home(long size)
        : m_land{new int[size] ()}{}
    
    ~home() { delete [] m_land;}

    home(home&& other);

    int* land() const { return m_land; }

    int* land_cp() const { return cp_land; }

    void copy()
    {
        cp_land = new int[a_size];
        for (int i = 0; i <= a_size; i++)
        {
            cp_land[i] = m_land[i];
        }
    }

    void del()
    {
        delete [] cp_land;
    }
};

home::home(home&& other)
    : m_land{other.m_land}
{
    other.m_land = nullptr;
}


int main()
{
    std::chrono::system_clock::time_point  start, end;
    start = std::chrono::system_clock::now();

    home A{a_size};
    std::cout << "A\'s land address : " << A.land() << std::endl;

    A.copy();
    std::cout << "A\'s cp_land address : " << A.land_cp() << std::endl;
    A.del();

    home B{std::move(A)};
    std::cout << "B\'s land address : " << B.land() << std::endl;

    std::cout << std::endl;
    end = std::chrono::system_clock::now();
    double elapsed = std::chrono::duration_cast(end-start).count();
    std::cout << "elapsed time : " << elapsed << " ms" << std::endl;
}

<結果>

・領域初期化有りモードではおおよそコピー時間差(領域初期化の有無で、領域コピー有りの時間にそれほど差はないのはなぜかと思うけど)、これを見ると領域の初期化も当然重い処理。

・領域初期化無では領域コピー実行の比重がほぼ100%、コピーしなければ1ms以下で処理完了してます。

・いずれにしろ、これらの処理が繰り返し実行される場合には大きなパーフォーマンスの差になるから、移譲は使える時には使ったほうが良い。

領域サイズ:100MB

<領域初期化有り>

・std::move
A's land address : 0x7ff049f00000
B's land address : 0x7ff049f00000

elapsed time : 166 ms

・+ 領域copy
A's land address : 0x7fb615700000
A's cp_land address : 0x7fb5f5700000
B's land address : 0x7fb615700000

elapsed time : 546 ms


<領域初期化無し>

・std::move
A's land address : 0x7fb23ff00000
B's land address : 0x7fb23ff00000

elapsed time : 0 ms

・+ 領域copy
A's land address : 0x7fb03df00000
A's cp_land address : 0x7fb01df00000
B's land address : 0x7fb03df00000

elapsed time : 514 ms

ソースは以下のリンクから、

https://github.com/chateight/c-plusplus/blob/master/move_perform.cpp

メモリ管理をマニュアルでやっていますが、vectorクラスのようなコンテナを使ったときのパーフォーマンスにも興味があります。

 

<疑問一点>

デストラクターでcp_landの解放すると、

*** error for object 0x7ff7b9aae490: pointer being freed was not allocated

のエラーが出ますが、なぜ?取り敢えずはdel()メソッド追加で対応してますが。

 

admin

 

gitignoreで実行ファイル除外の設定方法

GitHubに実行ファイルをアップロードしてもそれはマシン固有ファイルなので無意味です。じゃどうやって拡張子のついてない実行ファイルを管理対象外とするのか?

これに答えてくれるのが、

https://qiita.com/padawan_e15/items/7ba90f09e3ecd559f95b

にありますが、

.gitignoreファイルに以下のように記述すれば、

〇 まず、全部のファイルを管理対象外として、(下の一行目)

① ただし、ディレクトリ配下のディレクトリ全ては除外、すなわち管理対象とする(二行目)

② ただし、ディレクトリ内の拡張子のあるファイル全ては除外、すなわち管理対象とする(三行目)

<.gitignore>

*
!*/
!*.*

とすることで、拡張子のないファイルだけ指定したことになるという理屈。

こうすることでVScodeのエクスプローラから実行ファイルが消えました。

 

admin

M1 macでの(開発)環境の構築

アプリレベルならば、最近webにあまり情報がなくなってきたのは、互換性がそれなりに出てきたからだろうけど、M1になることによってアプリもさることながら、ディレクトリ構造やツール類(例えばHomebrew)もかなり変更があるから、intel macからの単純移行はあり得なくて、スクラッチからインストールしないとダメだろう。

・現状インストールが必要だろうと思うアプリ・ドライバの一覧、これ以外にVMware Fusionは現状ベータですが、いずれ安定して無償なら入れるつもり。

<ブラウザ、クラウドストレージ、Utility>

Chrome

Canon LBP6230 printer driver(rossetta2で動くのか)

CotEditor

DropBox

Karabiner elements

LanScan

Mega

OneDrive

PhotoScape

QfinderPro(Qnap NAS管理)

Speedtest

TimeMachineEditor

 

<開発環境とアプリ>

Arduino IDE:これはVScodeに移行するつもり

Blender

Clang

Fusion 360

FlashPrint(FLASHFORGE 3Dプリンター用)

Homebrew

Kicad

M5stack USB driver

Python(pipじゃなくてconda使うと)

Ruby

Processing

Raspberry pi imager

Scratch link

SD card formatter

Smart json editor

Sonic pi

Thonny

Unity

VScode

Visual Studio

Xcode

マイクラEE

 

admin

Bluesound Node導入三ヶ月

Raspberry piのVolumioとNodeを併存させておよそ三ヶ月経過ですが、NodeはSpotifyが無償版ということもあり音がイマイチ(15KHzでカット)なのと、数時間で切り替わって次を選ぶのも面倒に感じる時がある。プレイリスト作ればいいのかもしれないけれども。

その点Volumioのネットラジオは、320KbpsならCD qualityだし、似たジャンルあるいは作曲家の曲を流し続けてくれるから、手間かからずに便利。

従ってVolumioとNodeの使用比率も概ね半々ぐらいといったところ。サブスクの費用払おうとは思わないし、Amazon musicのハイレゾもコスト for バリューあるかと言われれば個人的には無いと思う。

 

admin

リサーチの結果は、

2018モデルのMacBook Air のdual core CPUではVScodeでPlatformIO立ち上げるぐらいでもファンが唸りを上げて、それでも1分ぐらい立ち上がりに時間かかるから、実質ブラウザとメモ帳ぐらいしか現実的ではありません。

で、apple silicon MacBookを何にするか?

条件は以下の6項目、

① intel MacBook 16の予備機としたいけどM1で性能的には同等だから問題ない

② 写真、動画のクリエーターでないのでM2(Air/Pro)のパーフォーマンスは今のところは無駄に不要

③ 一応モバイルとして使いたいから軽くはないけどモデルの中では軽いAir

④ VM、多くのパーツは扱わないけどFusion 360とか動かす前提だと8GBは心もとないから16GBに変更

⑤ SSD容量は④項を考慮するとVM用に50GBとかは割り当てるから256GBでは足りないから512GBに変更

⑥ キーボードは所詮かな入力しないし、16インチと合わせた方が使いやすい(かなりマストだと思う)からUSキーボードに変更

種々の環境もリリースからそろそろ二年経過でだいぶ整ってきているから替え時だろう。あと二年もすればintel Macは継子になるんだろうし。いずれにしてもUSキーボードを使う限りは、この先もCTO必須ということ。

 

P.S.

色はクリックしてから気づいたけどスペースグレイになってた、まあゴールドから変わるのも気分転換にはなる。

 

admin

MacBook Airで画面ロック掛からない?

いろいろ挙動不審だったのですが、最後に残ったのが画面閉じて開いた時にロックがかからないこと。

ググって、タイマー設定の問題、なんでここが変わったのかですが。

 

admin

M2 MacBook Air 7月15日から受注開始か、

今のMacBook Air 2018モデル、買ったのは2019年の今頃、も三年経過したし、そろそろApple Siliconへの移行準備も考えた方が良いだろうし。

となると、M2 MacBook Airは候補の一つですね。SSDは512GBで、メモリは16GBにした方が良さそうですが。画面は大きめが良いのは無論ですが、14/16インチのような性能は不要だし、モバイル用だとやはり最適は13インチになります。

外部モニターやiMacはやはり部屋の中では邪魔くさいから将来ともiMacを選択する可能性はなさそうで、やはり半固定の使い方で2019 intel MacBook16に慣れると16インチが麗しいけれども重たい。まあMacBookのラインナップって上手いこと考えられています。

P.S. @2022/7/8

今更ですが、本日日本時間9PMからオーダー受けるみたいですね。

 

admin

M5stackって色指定が16bit colorだったんだ

https://qiita.com/nnn112358/items/ea6b5e81623ba690343c

などで、M5stackの色指定は3バイトではなくuint16_tで指定されるので何でかなと思ったら、r/b : 5bit, g : 6bitの2バイトで表現されるんですね。

M5stackのディスプレイならば、それで問題ないだろうと思うし、メモリ使用量を少なくする考慮が種々なされてるから、それもアリなのでしょう。

 

admin

QwiicとSTEMMAインターフェース

https://www.switch-science.com/catalog/8183/

レーザー距離計のモジュールの商品説明に、STEMMAという名称のインターフェースが出てきて初耳なので調べてみた。それに上のリンクの商品紹介で「STEMMA QT/Qwiic互換」ともあってQwiicって何者?

STEMMAはピンピッチ2mm(gloveと同じ)の専用インターフェースでi2c以外もサポート、一方STEMMA QTは小型化のためにコネクタが1mmピッチでかつi2c専用です。じゃSTEMMA QTとQwiicはなにがちがうの?が知りたいこと。

で検索すると、以下が一番分かりやすい。

https://learn.adafruit.com/introducing-adafruit-stemma-qt?view=all

  • Qwiic is a bit newer than Grove, it’s only for use with I2C devices.
  • 物理形状の差ではなくてレベルシフターの有無だけのようだ、結果として3.3Vだけで使うならそのまま接続しても問題ない。
  • Compatibility:

Like Qwiic, STEMMA only uses the 4-pin connectors for I2C. The STEMMA QT connector is identical to the Qwiic connector and uses the same pin ordering.

  • Differences:

Qwiic only has level shifting and voltage regulation on the controller, not devices. So, you can use STEMMA + STEMMA QT devices with any Qwiic controller and you can use Qwiic devices on a STEMMA controller if you set the voltage jumper from 5V to 3V

この距離計、ターゲットが複数個でも検出できるというのが優れもの。『ヒストグラムベースのテクノロジー』というのが、それに該当していそうです。

 

admin