假设我有两个整数数组a
和b
,每个数组有10 int
s。有没有办法可以使用一些“memset”或“memcopy”技巧将b[i]
的内容添加到a[i]
?我只是寻找比明显的for循环w / a[i] += b[i]
等更快的东西。
答案 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;
}
a
和b
是分别包含10个元素,3和4的数组。添加两个valarray
会执行元素添加。还为valarray
定义了许多其他算术运算。
你必须测试它是否比显式循环更快。由于valarrays
是为此类操作而设计的,因此可能会以某种方式优化实现。
答案 5 :(得分:0)
不是我知道的。
明显的循环是否足够慢,你确实需要“更快”的东西?你怎么能改进它?