关于c和/或c ++中数组的愚蠢问题

时间:2011-03-17 04:14:48

标签: c++ c performance

假设我有两个整数数组ab,每个数组有10 int s。有没有办法可以使用一些“memset”或“memcopy”技巧将b[i]的内容添加到a[i]?我只是寻找比明显的for循环w / a[i] += b[i]等更快的东西。

6 个答案:

答案 0 :(得分:3)

“愚蠢” - 我认为这是一个很好的问题!

你说“添加”不是“复制”而我假设是x86:

void addintvector (int *dstp, const int *srcp, int nints)
{
  int *endp;

  endp=dst+nints;
  nints=srcp-dstp;    // reuse nints

  while (dstp!=endp)
  {
    *dstp+=*(dstp+nints);    // makes use of the [base+index*4] x86 addressing
    dstp+=1;    // some prefer ++dstp but I don't when it comes to pointers
  }
}

循环应转换为

add_label:
  mov eax,[ebx+esi*4]
  add [ebx],eax
  add ebx,4
  cmp ebx,edx
  jne add_label

每个循环有五个指令:它不会比这快得多!

克隆成减法,除法和乘法变量也很容易。

有人谈到使用GPU,但这要求1. GPU与应用程序接口,2。您的阵列足够大,可以克服相关的开销。

要克服呼叫/返回开销,您可以尝试将其声明为内联。

修改

我刚读过您的评论“因为它是针对移动设备上的游戏”而且我猜它不是x86平台,因此可能没有reg + reg *比例寻址模式。如果是这种情况,则应编写代码

void addintvector (int *dstp, const int *srcp, int nints)
{
  int *endp;

  endp=dst+nints;

  while (dstp!=endp)
  {
    *dstp+=*srcp;
    srcp+=1;
    dstp+=1;
  }
}

不知道你所针对的是哪种架构但是假设RISC我想代码将是8条指令(在“未优化的”伪代码中):

add_label:
  mov tempreg1,[srcreg]
  mov tempreg2,[dstreg]
  add tempreg2,tempreg1
  mov [dstreg],tempreg2
  add srcreg,4
  add dstreg,4
  cmp dstreg,endreg
  jne add_label

答案 1 :(得分:2)

简单的加法循环通常会足够快,因为编译器会对其进行矢量化:http://gcc.gnu.org/projects/tree-ssa/vectorization.html,输出并行指令,这些指令将同时对数组的四个元素进行操作。

答案 2 :(得分:2)

也许值得考虑OpenCL。如果你有很多矢量或矩阵任务,那就让我们解决GPU。看看带有向量https://www.wiki.ed.ac.uk/display/ecdfwiki/OpenCL+quick+start

之和的样本

答案 3 :(得分:1)

如果您愿意使用“纯”C,则C99中有可变参数宏。使用P99进行展开:

#include "p99_for.h"
#define ADDIT(Y, X, I) X[I] += Y[I]
#define ADD_MORE(Y, X, N) P99_FOR(Y, N, P00_SEP, ADDIT, P99_DUPL(N, X))

这样的行
ADD_MORE(A, B, 3);

然后扩展到

B[0] += A[0]; B[1] += A[1]; B[2] += A[2];

答案 4 :(得分:1)

std::valarray似乎是个不错的选择。

#include <valarray>
#include <algorithm>
#include <iostream>
#include <iterator>

int main()
{
    std::valarray<int> a(3, 10);
    std::valarray<int> b(4, 10);

    std::valarray<int> result = a + b;

    std::copy(&result[0], &result[0] + result.size(), 
        std::ostream_iterator<int>(std::cout, " "));

    return 0;
}

ab是分别包含10个元素,3和4的数组。添加两个valarray会执行元素添加。还为valarray定义了许多其他算术运算。

你必须测试它是否比显式循环更快。由于valarrays是为此类操作而设计的,因此可能会以某种方式优化实现。

答案 5 :(得分:0)

不是我知道的。

明显的循环是否足够慢,你确实需要“更快”的东西?你怎么能改进它?