我可以比这更快地将我的一维矢量转换为二维矢量吗?
Can I convert my 1D vector to a 2D vector faster than this?
这个问题很简单。经过一些试验,这是我发现的最有效的代码:
//For the sake of the example, I initialize every entry as zero.
vector<float> vector1D(1024 * 768, 0);
vector<vector<float>> vector2D(768, vector<float>(1024,0));
int counter = 0;
for (int i = 0; i < 768; i++) {
for (int j = 0; j < 1024; j++) {
vector2D[i][j] = vector1D[counter++];
}
}
有没有更快的方法?
使用 memcpy
可能会更快,因为这是用于复制内存的 API 的最低可能级别,并且可能存在可能使用特定指令等的编译器优化。并使 if 更快:
for (int i = 0; i < 768; i++) {
memcpy(vector2D[i].data(), &vector1D[i * 1024], sizeof(float) * 1024);
}
请记住,除了 trivially-copiable 数据外,您不应将 memcpy
用于任何其他内容。也就是说,它适用于 float
和 int
但不适用于 类,因为不会调用复制构造函数。
是的。
您可以重新映射您访问元素的方式而无需复制它们。您可以创建一个“视图”class 来实现:
template<typename T>
class two_dee_view
{
public:
two_dee_view(std::vector<T>& v, std::size_t row, std::size_t col)
: v(v), stride(col) { if(v.size() < row * col) v.resize(row * col); }
T& operator()(std::size_t row, std::size_t col)
{ return v[(row * stride) + col]; }
T const& operator()(std::size_t row, std::size_t col) const
{ return v[(row * stride) + col]; }
std::size_t col_size() const { return stride; }
std::size_t row_size() const { return v.size() / stride; }
private:
std::vector<T>& v;
std::size_t stride;
};
int main()
{
std::vector<double> v {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
two_dee_view<double> v2d(v, 2, 3);
for(auto row = 0U; row < v2d.row_size(); ++row)
for(auto col = 0U; col < v2d.col_size(); ++col)
std::cout << row << ", " << col << ": " << v2d(row, col) << '\n';
}
输出:
0, 0: 1
0, 1: 2
0, 2: 3
1, 0: 4
1, 1: 5
1, 2: 6
class 只是维护一个 reference 到 std::vector
你传递给 constructor。你应该只使用 two_dee_view
只要原来的 std::vector
存在但不再存在。
如果出于某种原因必须使用向量的向量,使用 memcpy
或 memmove
会更快(因为它是一个步骤,如另一个回复中所述)。但是你应该使用STL而不是自己做。
vector<float> vector1D(1024 * 768, 0);
vector<vector<float>> vector2D(768, vector<float>(1024, 0));
for (int i = 0; i < 768; i++) {
vector2D[i].assign(next(vector1D.cbegin(), 1024 * i),
next(vector1D.cbegin(), 1024 * (i + 1)));
}
这会导致直接 memmove
(取决于 STL 实现)但更安全、优化且(可能)可读。
这个问题很简单。经过一些试验,这是我发现的最有效的代码:
//For the sake of the example, I initialize every entry as zero.
vector<float> vector1D(1024 * 768, 0);
vector<vector<float>> vector2D(768, vector<float>(1024,0));
int counter = 0;
for (int i = 0; i < 768; i++) {
for (int j = 0; j < 1024; j++) {
vector2D[i][j] = vector1D[counter++];
}
}
有没有更快的方法?
使用 memcpy
可能会更快,因为这是用于复制内存的 API 的最低可能级别,并且可能存在可能使用特定指令等的编译器优化。并使 if 更快:
for (int i = 0; i < 768; i++) {
memcpy(vector2D[i].data(), &vector1D[i * 1024], sizeof(float) * 1024);
}
请记住,除了 trivially-copiable 数据外,您不应将 memcpy
用于任何其他内容。也就是说,它适用于 float
和 int
但不适用于 类,因为不会调用复制构造函数。
是的。
您可以重新映射您访问元素的方式而无需复制它们。您可以创建一个“视图”class 来实现:
template<typename T>
class two_dee_view
{
public:
two_dee_view(std::vector<T>& v, std::size_t row, std::size_t col)
: v(v), stride(col) { if(v.size() < row * col) v.resize(row * col); }
T& operator()(std::size_t row, std::size_t col)
{ return v[(row * stride) + col]; }
T const& operator()(std::size_t row, std::size_t col) const
{ return v[(row * stride) + col]; }
std::size_t col_size() const { return stride; }
std::size_t row_size() const { return v.size() / stride; }
private:
std::vector<T>& v;
std::size_t stride;
};
int main()
{
std::vector<double> v {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
two_dee_view<double> v2d(v, 2, 3);
for(auto row = 0U; row < v2d.row_size(); ++row)
for(auto col = 0U; col < v2d.col_size(); ++col)
std::cout << row << ", " << col << ": " << v2d(row, col) << '\n';
}
输出:
0, 0: 1
0, 1: 2
0, 2: 3
1, 0: 4
1, 1: 5
1, 2: 6
class 只是维护一个 reference 到 std::vector
你传递给 constructor。你应该只使用 two_dee_view
只要原来的 std::vector
存在但不再存在。
如果出于某种原因必须使用向量的向量,使用 memcpy
或 memmove
会更快(因为它是一个步骤,如另一个回复中所述)。但是你应该使用STL而不是自己做。
vector<float> vector1D(1024 * 768, 0);
vector<vector<float>> vector2D(768, vector<float>(1024, 0));
for (int i = 0; i < 768; i++) {
vector2D[i].assign(next(vector1D.cbegin(), 1024 * i),
next(vector1D.cbegin(), 1024 * (i + 1)));
}
这会导致直接 memmove
(取决于 STL 实现)但更安全、优化且(可能)可读。