見出し画像

C++の配列値コピーはどれが速いのか?【memcpy, copy, ...】


目的

マイコンの処理時間を高速化するため、値コピーを高速化したい場合があります。
よく言われているのが、for文で値をコピーすると遅いですよ、memcpyが早いですよ、というのがありますが、実際どのくらい違うのでしょう?

ネット検索してみると、いろんなケースで比較されており、memcpyが速い場合もあり、一方でstd::copyが速い場合もありました。
今回は、Arduino Dueで計測してみたいと思います。

条件

std::arrayを二つ定義し、

std::array<float, ARRAY_SIZE> array_copy_source;
std::array<float, ARRAY_SIZE> array_copy_destination;

サイズを100, 500の二つのパターンで実行してみました。

for文の式は、

for (std::size_t i = 0; i < BaseUtilityTester::ARRAY_SIZE; i++) {
  this->array_copy_destination[i] = this->array_copy_source[i];
}

std::memcpyの式は、

std::memcpy(this->array_copy_destination.data(),
            this->array_copy_source.data(),
            sizeof(float) * BaseUtilityTester::ARRAY_SIZE);

std::copyの式は、

std::copy(this->array_copy_source.begin(), this->array_copy_source.end(),
          this->array_copy_destination.begin());

です。

計測結果

$$
\begin{array}{|c|c|c|c|} \hline
配列サイズ & for文 & std::memcpy & std::copy \\ \hline
100 & 10[us] & 6[us] & 12[us] \\ \hline
500 & 43[us] & 24[us] & 43[us] \\ \hline
\end{array}
$$

やはり、std::memcpyが一番速いですね!
std::copyの方が安全性が高いので、どちらかと言えばこちらを使いたいのですが、速度面で結構劣ることが分かりました。for文とも大差ないとは…

処理系やコンパイラの最適化度合によって変わるので、必ずしも他のマイコンでもこのような比率になるかどうかは分かりません。

自作コピー関数の性能を調査

実は、テンプレートメタプログラミングを用いた自作の高速コピー関数を作成しています。
処理の中身としては、for文によるコピーと同じです。しかし、コンパイル時にforループを展開しているため、for文の条件判定を行わない分、高速に実行できます。

実行中にコピーする配列サイズを変更できなくなりますが、もし、コピーするサイズは実行中に変わらないのであれば、これでも全く問題ありません。

そのライブラリは以下に作成しています。

コードはこのように書きます。

Base::Utility::copy<float, BaseUtilityTester::ARRAY_SIZE>(
    this->array_copy_source, this->array_copy_destination);

それでは比較してみましょう。

$$
\begin{array}{|c|c|c|c|c|} \hline
配列サイズ & for文 & std::memcpy & std::copy & 自作 \\ \hline
100 & 10[us] & 6[us] & 12[us] & 6[us] \\ \hline
500 & 43[us] & 24[us] & 43[us] & 31[us] \\ \hline
\end{array}
$$

サイズが100の時はmemcpyと同等でした!
サイズが500の時は残念ながら負けてしまいました。しかし、for文やstd::copyより速いです。
もちろん、コピー範囲はコンパイル時に確定しているので、安全性の面でも高いです。

もしよろしければ是非活用していただければと思います。


いいなと思ったら応援しよう!