我有两个数组。一个是第二个大小的“x”因子。
我需要从第一个(较大的)数组复制到第二个(较小的)数组,只有它的 x 元素。意思是 0,x,2x。
每个数组都作为内存中的一个块。该数组具有简单的值。我目前正在使用循环进行。
有没有更快更聪明的方法来做到这一点?
也许与ostream
?谢谢!
你正在做这样的事情吗?
#include <cstddef>
int main()
{
const std::size_t N = 20;
const std::size_t x = 5;
int input[N*x];
int output[N];
for(std::size_t i = 0; i < N; ++i)
output[i] = input[i*x];
}
好吧,我不知道任何可以做到这一点的函数,所以我会使用 for 循环。这很快。
编辑:更快的解决方案(避免乘法)(C ++ 03版本)
int* inputit = input;
int* outputit = output;
int* outputend = output+N;
while(outputit != outputend)
{
*outputit = *inputit;
++outputit;
inputit+=x;
}
copy_if(a.begin(), a.end(), b.end(), [&] (const int& i) -> bool
{ size_t index = &i - &a[0]; return index % x == 0; });
一个测试用例是:
#include <iostream>
#include <vector>
#include <algorithm> // std::copy_if
using namespace std;
int main()
{
std::vector<int> a;
a.push_back(0);
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(4);
std::vector<int> b(3);
int x = 2;
std::copy_if(a.begin(), a.end(), b.begin(), [&] (const int& i) -> bool
{ size_t index = &i - &a[0]; return index % x == 0; });
for(int i=0; i<b.size(); i++)
{
std::cout<<" "<<b[i];
}
return 0;
}
请注意,您需要使用与 C++11 兼容的编译器(如果是 gcc,则使用 -std=c++11 选项)。
如果我猜对了,您想复制每个第 n 个元素。最简单的解决方案是
#include <iostream>
int main(int argc, char **argv) {
const int size[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int out[5];
int *pout = out;
for (const int *i = &size[0]; i < &size[10]; i += 3) {
std::cout << *i << ", ";
*pout++ = *i;
if (pout > &out[4]) {
break;
}
}
std::cout << "\n";
for (const int *i = out; i < pout; i++) {
std::cout << *i << ", ";
}
std::cout << std::endl;
}
template<typename InIt, typename OutIt>
void copy_step_x(InIt first, InIt last, OutIt result, int x)
{
for(auto it = first; it != last; std::advance(it, x))
*result++ = *it;
}
int main()
{
std::array<int, 64> ar0;
std::array<int, 32> ar1;
copy_step_x(std::begin(ar0), std::end(ar0), std::begin(ar1), ar0.size() / ar1.size());
}
这样做的正确和干净的方法是像之前所说的那样循环。这里有一些很好的答案向您展示了如何做到这一点。
我不建议按照以下方式进行操作,这取决于很多具体的事情,X 的值范围,变量的大小和值范围等等,但对于某些人来说,你可以这样做:
for every 4 bytes:
tmp = copy a 32 bit variable from the array, this now contains the 4 new values
real_tmp = bitmask tmp to get the right variable of those 4
add it to the list
这仅在您想要值 <= 255 和 X==4 时才有效,但如果您想要比循环更快的东西,这是一种方法。这可以针对 16 位、32 位或 64 位值以及每个 2、3、4、5、6、7、8(64 位)值进行修改,但对于 X>8,此方法将不起作用,或者对于未分配的值线性时尚。它也不适用于课程。
为了让这种优化值得经常运行代码的麻烦,我假设您已经运行了一个分析器来确认旧副本是一个瓶颈,然后再开始实现这样的东西。
以下是关于大多数 CPU 设计在这类事情上缺乏想象力的观察。
在某些 OpenVPX 上,您可以将数据从一个处理器发送到另一个处理器。我使用的那个有一个非常先进的 DMA 控制器,它可以为你做这种事情。
例如,我可以要求它将您的大数组复制到另一个 CPU,但跳过数组的 N 个元素,就像您尝试做的那样。就好像目标 CPU 会在其内存中拥有更小的数组一样。如果我想执行矩阵转换等,我也可以。
好消息是这样做完全不需要 CPU 时间。这一切都由 DMA 引擎完成。然后,我的 CPU 可以专注于更难的总和,而不是被束缚在四处打乱数据。
我认为 PS3 中的 Cell 处理器可以在内部做这种事情(我知道它可以 DMA 周围的数据,我不知道它是否会同时进行条带挖掘)。一些 DSP 芯片也可以做到这一点。但是 x86 不这样做,这意味着我们的软件程序员必须编写荒谬的循环,只是以简单的模式移动数据。打哈欠。
我过去写了一个多线程的 memcpy() 来做这种事情。击败 for 循环的唯一方法是让多个线程在多个并行块中执行 for 循环。
如果您选择了正确的编译器(例如 Intel 的 ICC 或 Sun/Oracles Sun Studio),它们可以代表您自动并行化您的 for 循环(因此您的源代码不会改变)。这可能是击败原始 for 循环的最简单方法。