假设我有2个strutcures s1
和s2
,每个包含10000个元素的数组。如果我将一个结构复制到另一个结构,如s1=s2
,则循环从1到10000,然后再s1[i]=s2[i]
。两种方法之间会有任何速度差异吗?如果是,那么请告诉哪一个更快,为什么?
答案 0 :(得分:2)
在我的编译器上,所有这些转换为对memcpy()
类函数的调用。它们碰巧是不同的,但编译器或多或少地认识到所有这些实现在功能上是相同的。
这些不同的memcpy()
实现之间的性能差异可能很小。
#include <stdlib.h>
#include <string.h>
struct S {
int x[10000];
};
void impl1(struct S *x, struct S *y) __attribute__((noinline));
void impl1(struct S *x, struct S *y) {
*x = *y;
}
void impl2(struct S *x, struct S *y) __attribute__((noinline));
void impl2(struct S *x, struct S *y) {
memcpy(x, y, sizeof(*x));
}
void impl3(struct S * restrict x, struct S * restrict y) __attribute__((noinline));
void impl3(struct S * restrict x, struct S * restrict y) {
for (int i=0; i<10000; ++i)
x->x[i] = y->x[i];
}
int main() {
struct S x, y;
impl1(&x, &y);
impl2(&x, &y);
impl3(&x, &y);
}
define void @impl1(%struct.S* nocapture %x, %struct.S* nocapture readonly %y) #0 {
%1 = bitcast %struct.S* %x to i8*
%2 = bitcast %struct.S* %y to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* %2, i64 40000, i32 4, i1 false), !tbaa.struct !1
ret void
}
define void @impl2(%struct.S* %x, %struct.S* %y) #0 {
%1 = bitcast %struct.S* %x to i8*
%2 = bitcast %struct.S* %y to i8*
%3 = tail call i64 @llvm.objectsize.i64.p0i8(i8* %1, i1 false)
%4 = tail call i8* @__memcpy_chk(i8* %1, i8* %2, i64 40000, i64 %3) #1
ret void
}
define void @impl3(%struct.S* noalias nocapture %x, %struct.S* noalias nocapture readonly %y) #0 {
%x2 = bitcast %struct.S* %x to i8*
%y3 = bitcast %struct.S* %y to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %x2, i8* %y3, i64 40000, i32 4, i1 false)
ret void
}
[10:04am][wlynch@watermelon /tmp] clang -v
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix
答案 1 :(得分:0)
我认为编译器为表达式s1 = s2
生成的代码将比明确使用用户定义的循环更快。编译器很可能会使用stnadard C函数memcpy