-1

我有两个数组。一个是第二个大小的“x”因子。

我需要从第一个(较大的)数组复制到第二个(较小的)数组,只有它的 x 元素。意思是 0,x,2x。

每个数组都作为内存中的一个块。该数组具有简单的值。我目前正在使用循环进行。

有没有更快更聪明的方法来做到这一点?

也许与ostream?谢谢!

4

6 回答 6

2

你正在做这样的事情吗?

#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;
}
于 2013-07-31T05:44:47.003 回答
1

您可以在 C++11中使用copy_iflambda :

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 选项)。

于 2013-07-31T05:52:01.753 回答
1

如果我猜对了,您想复制每个第 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;
}
于 2013-07-31T06:04:41.653 回答
1
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());
}
于 2013-07-31T06:26:04.757 回答
0

这样做的正确和干净的方法是像之前所说的那样循环。这里有一些很好的答案向您展示了如何做到这一点。

我不建议按照以下方式进行操作,这取决于很多具体的事情,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,此方法将不起作用,或者对于未分配的值线性时尚。它也不适用于课程。

为了让这种优化值得经常运行代码的麻烦,我假设您已经运行了一个分析器来确认旧副本是一个瓶颈,然后再开始实现这样的东西。

于 2013-07-31T06:10:11.583 回答
0

以下是关于大多数 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 循环的最简单方法。

于 2013-07-31T06:44:10.297 回答