C++ 算法:取出数组中的每4项

C++ 算法:取出数组中的每4项,c++,c,arrays,algorithm,real-time,C++,C,Arrays,Algorithm,Real Time,我有两个巨大的数组(在下面的代码中是int-source[1000],dest[1000],但实际上有数百万个元素)。源数组包含一系列ints,我希望每4个中复制3个 例如,如果源阵列为: int source[1000] = {1,2,3,4,5,6,7,8....}; int dest[1000]; 这是我的密码: for (int count_small = 0, count_large = 0; count_large < 1000; count_small += 3, coun

我有两个巨大的数组(在下面的代码中是int-source[1000],dest[1000],但实际上有数百万个元素)。源数组包含一系列
int
s,我希望每4个中复制3个

例如,如果源阵列为:

int source[1000] = {1,2,3,4,5,6,7,8....};
int dest[1000];
这是我的密码:

for (int count_small = 0, count_large = 0; count_large < 1000; count_small += 3, count_large +=4)
    {
      dest[count_small] = source[count_large];
      dest[count_small+1] = source[count_large+1];
      dest[count_small+2] = source[count_large+2];
    }
但是这个算法太慢了!是否有我可以使用/包含的算法或开源函数

谢谢:)

编辑:我的数组的实际长度约为100万(640*480*3)


编辑2:处理此for循环大约需要0.98秒到2.28秒,而其他代码只需要0.08秒到0.14秒,因此设备仅对循环使用至少90%的cpu时间

您可以尝试
memcpy
而不是单独分配:

memcpy(&dest[count_small], &source[count_large], sizeof(int) * 3);

好吧,这里的渐近复杂性是它将得到的最好结果。通过将值加载为四个4路SIMD整数,将它们混洗为三个4路SIMD整数,然后将它们写回,您可能会获得稍好的性能,但即使这样也不太可能快得多


尽管如此,处理1000个元素(编辑:或一百万个元素)的时间将是微不足道的。如果您认为这是程序中的瓶颈,那么您就错了。

在做更多工作之前,请尝试分析您的应用程序,并确定这是否是花费时间的最佳地方。然后,如果这是一个热点,确定它的速度有多快,以及您需要/可能实现的速度有多快?然后测试备选方案;线程或OpenMP的开销甚至可能会降低它的速度(特别是,正如您现在所注意到的,如果您使用的是单核处理器——在这种情况下,它不会有任何帮助)。对于单线程,根据Sean的回答,我将使用
memcpy

@斯奈夫特尔还参考了以下内容

一个选择是尝试并行处理循环,看看这是否有帮助。您可以尝试使用OpenMP标准(请参阅),但您必须针对您的具体情况进行尝试,看看它是否有帮助。我最近在一个AI实现中使用了它,它对我们帮助很大

#pragma omp parallel for
for (...)
{
   ... do work
}
除此之外,您仅限于编译器自己的优化

您还可以查看C11中最近的线程支持,尽管您最好使用预先实现的框架工具,如(在Visual Studio中提供,如果您正在使用的话),而不是使用自己的工具

parallel_for(0, max_iterations,
    [...] (int i)
    {
        ... do stuff
    }
);
for
循环中,您还有其他选项。您可以尝试一个for循环,该循环每for进行一次迭代和跳过,而不是每次迭代执行3个副本(当
(i+1)%4==0时跳过),或者根据对3个整数的组执行块操作。对于其中一些,您可能会实现稍有不同的编译器优化,但这不太可能(
memcpy
可能与您所获得的速度一样快)

for(inti=0,intj=0;i<1000;i++)
{
如果((i+1)%4!=0)
{ 
dest[j]=源[i];
j++;
}
}

然后,您应该开发一个测试平台,以便能够快速地进行性能测试,并确定最适合您的测试平台。最重要的是,在其他地方进行优化之前,请确定在这方面值得花费多少时间。

您的阵列大小是否只有1000?如果是这样,它的速度有多慢?这件事应该马上完成! 只要您正在为单线程应用程序创建一个新阵列,这就是唯一的解决方案

但是,如果数据集很大,可以尝试使用多线程应用程序


此外,您还可以探索使用更大的数据类型来保存该值,从而减小数组大小。。。也就是说,如果这对您的实际应用程序是可行的这是C还是C问题,Guntram?你的标签上写的是C,但我不确定这是否是一个错误鉴于数组定义,它肯定不是C。这么慢???只有1000个元素,而C++(+)循环以最优的方式完成这些事情。一定非常快(不到一微秒)!你没告诉我们的是什么?你用的是什么处理器?一些(特别是DSP)具有嵌入式2D DMA复制操作,因此您可以将
源代码
称为nx4矩阵,并从中复制一个nx3块到
dest
。您为什么说您的解决方案很慢?在程序中对这些元素执行任何其他操作都需要更长的时间!这没用。编译器是智能的,所以像这样的优化将自动完成。即使没有。它不会让这么慢的算法变快;不确定它是否会提高性能,尤其是如果您启用编译器优化以进行循环展开!我将使用
-O3
进行测试,看看它是什么样子。硬编码
12
非常糟糕。至少,我会使用
sizeof(source[0])*3
.FWIW-
memcpy
方法比使用
-O3
(gcc 4.6.3)的“一次一个”方法快约15%,而OpenMP在这方面真的不太可能提供好处,正如您所说的,开销可能会使其速度大大降低。当前代码将使内存带宽饱和,除非他对分配和分段非常小心,否则使用多个线程将导致错误共享惩罚。同意-但如果(且仅当)这是一个确定的瓶颈,需要解决性能问题,然后它将是值得快速尝试不同的选项和性能测试他们我希望这个解决方案的工作,我也会尝试它!不幸的是,运行它的处理器是单核处理器,因此我不确定多线程是否能在这个设备上工作。如果您只有一个单核,那么忘记多线程,这只会降低您的速度。而
(I+1)%4!=0
代码看起来相当不错,不幸的是它没有加快速度,速度保持在2.09秒到2.27秒之间
parallel_for(0, max_iterations,
    [...] (int i)
    {
        ... do stuff
    }
);
for (int i = 0, int j = 0; i < 1000; i++)
{
  if ((i+1) % 4 != 0)
  { 
    dest[j] = source[i];
    j++;
  }
}