提案された解決策に基づいて、小さなベンチマークをまとめることにしました。これは次の出力を生成
完全に最適化されmsvc100でのx64用にコンパイルされた私のPCで
#include <cstdint>
#include <cstring>
#include <ctime>
#include <iostream>
#include <random>
#include <vector>
using namespace std;
int main()
{
random_device seed;
mt19937 rnd(seed());
uniform_int_distribution<uint8_t> random_byte(0x00, 0xff);
const size_t n = 512 * 512;
vector<uint8_t> source;
source.reserve(n);
for (size_t i = 0; i < n; i++) source.push_back(random_byte(rnd));
clock_t start;
clock_t t_constructor1 = 0; uint8_t c_constructor1 = 0;
clock_t t_constructor2 = 0; uint8_t c_constructor2 = 0;
clock_t t_assign = 0; uint8_t c_assign = 0;
clock_t t_copy = 0; uint8_t c_copy = 0;
clock_t t_memcpy = 0; uint8_t c_memcpy = 0;
for (size_t k = 0; k < 4; k++)
{
start = clock();
for (size_t i = 0; i < n/32; i++)
{
vector<uint8_t> destination(source);
c_constructor1 += destination[i];
}
t_constructor1 += clock() - start;
start = clock();
for (size_t i = 0; i < n/32; i++)
{
vector<uint8_t> destination(source.begin(), source.end());
c_constructor2 += destination[i];
}
t_constructor2 += clock() - start;
start = clock();
for (size_t i = 0; i < n/32; i++)
{
vector<uint8_t> destination;
destination.assign(source.begin(), source.end());
c_assign += destination[i];
}
t_assign += clock() - start;
start = clock();
for (size_t i = 0; i < n/32; i++)
{
vector<uint8_t> destination(source.size());
copy(source.begin(), source.end(), destination.begin());
c_copy += destination[i];
}
t_copy += clock() - start;
start = clock();
for (size_t i = 0; i < n/32; i++)
{
vector<uint8_t> destination(source.size());
memcpy(&destination[0], &source[0], n);
c_memcpy += destination[i];
}
t_memcpy += clock() - start;
}
// Verify that all copies are correct, but also prevent the compiler
// from optimising away the loops
uint8_t diff = (c_constructor1 - c_constructor2) +
(c_assign - c_copy) +
(c_memcpy - c_constructor1);
if (diff != 0) cout << "one of the methods produces invalid copies" << endl;
cout << "constructor (1): " << t_constructor1 << endl;
cout << "constructor (2): " << t_constructor2 << endl;
cout << "assign: " << t_assign << endl;
cout << "copy " << t_copy << endl;
cout << "memcpy " << t_memcpy << endl;
return 0;
}
、、、:
constructor (1): 22388
constructor (2): 22333
assign: 22381
copy 2142
memcpy 2146
結果は非常に明確である:両方のコンストラクタのに対しstd::copy
行なうだけでなく、std::memcpy
、およびassign
は1桁小さいです。もちろん、正確な数値と比率はベクトルサイズに依存しますが、msvc100の結論は明らかです。suggested by Rapptzとしてstd::copy
を使用してください。
編集:結論は他のコンパイラにとって明らかではありません。私は64ビットLinuxでも同様にテストを行い、Clangの次の結果を得ました。3.2
GCC 4.8は同様の出力を示します。WindowsのGCCの場合、memcpy
とcopy
はコンストラクターよりわずかに遅く、assign
ですが、その差は小さかったです。しかし、私の経験は、GCCはWindows上で非常にうまく最適化されないということです。私もmsvc110をテストしましたが、結果はmsvc100に似ていました。
通常の 'std :: copy'を試しましたか? – Rapptz
最適化されたビルドでテストしましたか? – StackedCrooked
std :: copyを使用してみませんか? –