W poniższym programie mam 2 bufory, jeden z nich jest wyrównany do 64 bitów, a drugi, który zakładam, jest wyrównany na 16 bajtów na moim 64 serwerze Linuxa z jądrem 2.6.x.Dlaczego dostęp do bufora z pamięcią w pamięci jest droższy w systemie Linux?
Linia pamięci podręcznej ma długość 64 bajtów. Tak więc w tym programie po prostu uzyskuję dostęp do jednej linii pamięci podręcznej na raz. Miałem nadzieję, że zobaczę, że posix_memaligned
jest równy, jeśli nie jest szybszy niż bufor bez wyrównania. Oto dane
./readMemory 10000000
time taken by posix_memaligned buffer: 293020299
time taken by standard buffer: 119724294
./readMemory 100000000
time taken by posix_memaligned buffer: 548849137
time taken by standard buffer: 211197082
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/time.h>
void now(struct timespec * t);
int main(int argc, char **argv)
{
char *buf;
struct timespec st_time, end_time;
int runs;
if (argc !=2)
{
printf("Usage: ./readMemory <number of runs>\n");
exit(1);
}
errno = 0;
runs = strtol(argv[1], NULL, 10);
if (errno !=0) {
printf("Invalid number of runs: %s \n", argv[1]);
exit(1);
}
int returnVal = -1;
returnVal = posix_memalign((void **)&buf, 64, 1024);
if (returnVal != 0)
{
printf("error in posix_memaligh\n");
}
char tempBuf[64];
char * temp = buf;
size_t cpyBytes = 64;
now(&st_time);
for(int x=0; x<runs; x++) {
temp = buf;
for(int i=0; i < ((1024/64) -1); i+=64)
{
memcpy(tempBuf, temp, cpyBytes);
temp += 64;
}
}
now(&end_time);
printf("time taken by posix_memaligned buffer: %ld \n", (end_time.tv_nsec - st_time.tv_nsec));
char buf1[1024];
temp = buf1;
now(&st_time);
for(int x=0; x<runs; x++)
{
temp = buf1;
for(int i=0; i < ((1024/64) -1); i+=64)
{
memcpy(tempBuf, temp, cpyBytes);
temp += 64;
}
}
now(&end_time);
printf("time taken by standard buffer: %ld \n", (end_time.tv_nsec - st_time.tv_nsec));
return 0;
}
void now(struct timespec *tnow)
{
if(clock_gettime(CLOCK_MONOTONIC_RAW, tnow) <0)
{
printf("error getting time");
exit(1);
}
}
rozkładanie do pierwszej pętli
movq -40(%rbp), %rdx
movq -48(%rbp), %rcx
leaq -176(%rbp), %rax
movq %rcx, %rsi
movq %rax, %rdi
call memcpy
addq $64, -48(%rbp)
addl $64, -20(%rbp)
demontaż drugiego pętli
movq -40(%rbp), %rdx
movq -48(%rbp), %rcx
leaq -176(%rbp), %rax
movq %rcx, %rsi
movq %rax, %rdi
call memcpy
addq $64, -48(%rbp)
addl $64, -4(%rbp)
Czy możesz pokazać demontaż dwóch wewnętrznych pętli? – Mysticial
Jasne, że nie ma to nic wspólnego z montażem ... hehe – Mysticial
Moja wersja GCC optymalizuje pętle do zera ... więc oba działają równie szybko. To na Mac OS X 10.8.2 z 'i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (na podstawie Apple Inc. build 5658) (LLVM build 2336.11.00)'. –