我想在将elements属性设置为零时复制矢量.我有一个std::vector<PLY>包含特定数量的以下struct元素的向量:
struct PLY{
float x;
float y;
float z;
}
Run Code Online (Sandbox Code Playgroud)
什么是创建这个载体,其中每一层元素有一个副本的最快方法z-value的0?有没有更快的方法然后创建向量的副本,然后迭代每个元素以设置新的z值?
什么是最快的方式...?
测试一下。内存架构做了令人惊讶的事情。
#include <iostream>
#include <chrono>
#include <vector>
#include <iomanip>
#include <algorithm>
struct PLY
{
PLY() : x(0), y(0), z(0) {}
PLY(float x, float y, float z) : x(x), y(y), z(z) {}
float x, y , z;
};
template<class F>
std::vector<PLY> test(const char* name, std::vector<PLY> samples, F f)
{
using namespace std::literals;
std::vector<PLY> result;
result.reserve(samples.size());
auto start = std::chrono::high_resolution_clock::now();
f(result, samples);
auto end = std::chrono::high_resolution_clock::now();
using fns = std::chrono::duration<long double, std::chrono::nanoseconds::period>;
using fms = std::chrono::duration<long double, std::chrono::milliseconds::period>;
using fs = std::chrono::duration<long double, std::chrono::seconds::period>;
auto interval = fns(end - start);
auto time_per_sample = interval / samples.size();
auto samples_per_second = 1s / time_per_sample;
std::cout << "testing " << name << '\n';
std::cout << " sample size : " << samples.size() << '\n';
std::cout << " time taken : " << std::fixed << fms(interval).count() << "ms\n";
std::cout << " time per sample : " << std::fixed << (interval / samples.size()).count() << "ns\n";
std::cout << " samples per second : " << std::fixed << samples_per_second << "\n";
return result;
}
struct zero_z_iterator : std::vector<PLY>::const_iterator
{
using base_class = std::vector<PLY>::const_iterator;
using value_type = PLY;
using base_class::base_class;
value_type operator*() const {
auto const& src = base_class::operator*();
return PLY{ src.x, src.y, 0.0 };
}
};
int main()
{
test("transform", std::vector<PLY>(1000000), [](auto& target, auto& source)
{
std::transform(source.begin(), source.end(),
std::back_inserter(target),
[](auto& ply) {
return PLY { ply.x, ply.y, ply.z };
});
});
test("copy and reset z", std::vector<PLY>(1000000), [](auto& target, auto& source)
{
std::copy(source.begin(), source.end(),
std::back_inserter(target));
for (auto& x : target)
{
x.z = 0;
}
});
test("hand_roll", std::vector<PLY>(1000000), [](auto& target, auto& source)
{
for(auto& x : source) {
target.emplace_back(x.x, x.y, 0.0);
}
});
test("assign through custom iterator", std::vector<PLY>(1000000), [](auto& target, auto& source)
{
target.assign(zero_z_iterator(source.begin()),
zero_z_iterator(source.end()));
});
test("transform", std::vector<PLY>(100000000), [](auto& target, auto& source)
{
std::transform(source.begin(), source.end(),
std::back_inserter(target),
[](auto& ply) {
return PLY { ply.x, ply.y, ply.z };
});
});
test("copy and reset z", std::vector<PLY>(100000000), [](auto& target, auto& source)
{
std::copy(source.begin(), source.end(),
std::back_inserter(target));
for (auto& x : target)
{
x.z = 0;
}
});
test("hand_roll", std::vector<PLY>(100000000), [](auto& target, auto& source)
{
for(auto& x : source) {
target.emplace_back(x.x, x.y, 0.0);
}
});
test("assign through custom iterator", std::vector<PLY>(100000000), [](auto& target, auto& source)
{
target.assign(zero_z_iterator(source.begin()),
zero_z_iterator(source.end()));
});
}
Run Code Online (Sandbox Code Playgroud)
testing transform
sample size : 1000000
time taken : 7.495685ms
time per sample : 7.495685ns
samples per second : 133410088.604310
testing copy and reset z
sample size : 1000000
time taken : 3.436614ms
time per sample : 3.436614ns
samples per second : 290984090.735823
testing hand_roll
sample size : 1000000
time taken : 3.289287ms
time per sample : 3.289287ns
samples per second : 304017253.587176
testing assign through custom iterator
sample size : 1000000
time taken : 2.563334ms
time per sample : 2.563334ns
samples per second : 390116933.649692
testing transform
sample size : 100000000
time taken : 768.941767ms
time per sample : 7.689418ns
samples per second : 130048859.733744
testing copy and reset z
sample size : 100000000
time taken : 880.893920ms
time per sample : 8.808939ns
samples per second : 113521046.892911
testing hand_roll
sample size : 100000000
time taken : 769.276240ms
time per sample : 7.692762ns
samples per second : 129992315.894223
testing assign through custom iterator
sample size : 100000000
time taken : 689.493098ms
time per sample : 6.894931ns
samples per second : 145034084.155546
Run Code Online (Sandbox Code Playgroud)
通过自定义转换迭代器进行分配。
template<class Container, class Iter, class TransformFunction>
void assign_transform(Container& target, Iter first, Iter last, TransformFunction func)
{
struct transform_iterator : Iter
{
using base_class = Iter;
using value_type = typename Iter::value_type;
transform_iterator(Iter base, TransformFunction& f)
: base_class(base), func(std::addressof(f))
{}
value_type operator*() const {
auto const& src = base_class::operator*();
return (*func)(src);
}
TransformFunction* func;
};
target.assign(transform_iterator(first, func),
transform_iterator(last, func));
}
Run Code Online (Sandbox Code Playgroud)
像这样使用:
assign_transform(target, source.begin(), source.end(),
[](auto& from)
{
return PLY(from.x, from.y, 0.0);
});
Run Code Online (Sandbox Code Playgroud)
你可以使用std::transform:
std::vector<PLY> zeroed{};
zeroed.reserve(other_vec.size()); //pre-allocate the storage
std::transform(other_vec.begin(), other_vec.end(), std::back_inserter(zeroed),
[](auto e){ e.z = 0.f; return e; });
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
200 次 |
| 最近记录: |