在c ++中使用掩码复制数组的有效方法

时间:2013-07-31 05:25:07

标签: c++ arrays

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

我需要从第一个(较大的)数组复制到第二个(较小的)数组只复制其x元素。 含义0,x,2x。

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

有更聪明的方法吗?

也许是ostream? 谢谢!

6 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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选项)。

答案 2 :(得分: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;
}

答案 3 :(得分: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());
}

答案 4 :(得分: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

这只适用于你想要的值&lt; = 255和X == 4,但是如果你想要一个比循环更快的东西,这是一种方法。这可以修改为16位,32位或64位值和每2,3,4,5,6,7,8(64位)值,但对于X> 8,此方法将不起作用,或者对于未分配的值线性时尚。它也不适用于课程。

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

答案 5 :(得分:0)

以下是对大多数CPU设计在这类事情上缺乏想象力的观察。

在某些OpenVPX上,您可以将数据从一个处理器DMA到另一个处理器。我使用的那个有一个非常先进的DMA控制器,它可以为你做这种事情。

例如,我可以要求它将你的大数组复制到另一个CPU,但跳过数组的N个元素,就像你想要做的那样。好像通过魔术一样,目标CPU将在其内存中具有较小的阵列。如果我想要执行矩阵变换等,我也可以。

好处是它完全没有CPU时间;这一切都是由DMA引擎完成的。然后,我的CPU可以集中精力处理更难的数据,而不是将数据混乱。

我认为PS3中的Cell处理器可以在内部执行此类操作(我知道它可以绕DMA数据,我不知道它是否会同时进行条带挖掘)。一些DSP芯片也可以做到。但是x86没有这样做,这意味着我们的软件程序员必须编写荒谬的循环,只是以简单的模式移动数据。打哈欠。

我过去编写了一个多线程memcpy()来做这种事情。你打败for循环的唯一方法是让几个线程在几个并行的块中进行for循环。

如果选择正确的编译器(例如Intel的ICC或Sun / Oracles Sun Studio),可以代表您自动并行化for循环(因此您的源代码不会更改)。这可能是打败原始循环的最简单方法。