3 ms·
(not the author) What do you mean hot loading? In both cases we write to c, I don't think c needs to be in the cache at all. (Despite my belief this wasn't the
by enqk 15y ago
(not the author)
What do you mean hot loading? In both cases we write to c, I don't think c needs to be in the cache at all. (Despite my belief this wasn't the difference, I also tested pre-initialization and it does not make a difference)
However I checked the inner loop's asm and there are differences. The addition part is exactly the same, however the C code has an extra instruction which I do not understand the origin of:
c version:
0x1e84 movsd -8(%edi, %eax, 8), %xmm0 ! Loop start[3], SSE
0x1e8a movl -32(%ebp), %edx
0x1e8d addsd -8(%edx, %eax, 8), %xmm0
0x1e93 movsd %xmm0, -8(%esi, %eax, 8)
0x1e99 incl %eax
0x1e9f jnz 0x00001e84 <main+154> Loop end[3]
c++ version:
0x2ac2 movsd (%ecx, %eax, 8), %xmm0 ! Loop start[1], SSE
0x2ac7 addsd (%edi, %eax, 8), %xmm0
0x2acc movsd %xmm0, (%esi, %eax, 8)
0x2ad1 incl %eax
0x2ad4 jnz 0x00002ac2 <main+312> Loop end[1]
- hermanhermitage 15y agovector<double> c(MM); => Initializes all c[i] to 0.0. Thus it writes to each entry (causing a cache fill or cache allocate depending on copy-back versus write-thru configuration of cache). Thus in the timed C++ loop access to c[] is mainly at minimal latency. To reproduce the behaviour change the C init to: for(i = 0; i < MM; ++i){ a[i] = 1.0/(double)(i+1); b[i] = a[i]; c[i] = 0; } Then your times will coincide. On my machine here the inner loops are identical: gcc -O9 test.c -S: callq _clock movq %rax, %r13 .align 4, 0x90 LBB2_3: movsd (%rbx,%r12,8), %xmm0 addsd (%r14,%r12,8), %xmm0 movsd %xmm0, (%r15,%r12,8) incq %r12 cmpq $90000000, %r12 jne LBB2_3 callq _clock g++ -O9 test.cc -S callq _clock movq %rax, %r13 .align 4, 0x90 LBB5_19: movsd (%rbx,%r12,8), %xmm0 addsd (%r14,%r12,8), %xmm0 movsd %xmm0, (%r15,%r12,8) incq %r12 cmpq $90000000, %r12 jne LBB5_19 callq _clock (gcc/g++ 4.2 on Mac OS X) Furthermore, compiling on Intel Fortran with the same change to pre load c into cache: do i = 1,MM a(i) = 1.0/dble(i) b(i) = a(i) c(i) = 0.0 enddo and compiling with ifort -fast test.f90, I get a performance 1.33x greater in fortran than C/C++. C: 0.168993 C++: 0.169194 F90: 0.122215 Intel Fortran is compiling with more aggressive detection of AVX etc out of the box. A modern version of GCC or adding compiler switches might get it to meet the f90 figures. So this all highlights how difficult micro benchmarks are to get right. It's much easier to measure sustained thruput than create accurate micro benchmarks.