我有一个C程序,用C计算页面错误服务时间.
对于这个程序,我有2个大文件(每个小于3GB – 几乎与RAM的大小)
对于这个程序,我有2个大文件(每个小于3GB – 几乎与RAM的大小)
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include "rdstc.h" #include "config.h" #define KB 1024 #define MB 1024 * KB #define GB 1024 * MB #define SIZE_OF_MEMORY 1 * GB // Main memory size #define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) int main(int argc,char *argv[]){ int fd1,fd2; char *addr1,*addr2,c; int i,j; long long unsigned int s_t,e_t,t=0; if (argc != 3){ printf("usage: a.out <file1> <file2> \n"); exit(EXIT_FAILURE); } if ((fd1 = open(argv[1],O_RDONLY)) == -1){ handle_error("open"); } if ((fd2 = open(argv[2],O_RDONLY)) == -1){ handle_error("open"); } posix_fadvise(fd1,POSIX_FADV_RANDOM); posix_fadvise(fd2,POSIX_FADV_RANDOM); addr1 = (char *) mmap(0,SIZE_OF_MEMORY,PROT_READ,MAP_PRIVATE | MAP_POPULATE,fd1,0); if (addr1 == MAP_Failed){ handle_error("mmap"); } addr2 = (char *) mmap(0,fd2,0); if (addr2 == MAP_Failed){ handle_error("mmap"); } madvise(addr1,MADV_RANDOM); madvise(addr2,MADV_RANDOM); j = 32; // default read ahead size if 256 blocks (assuming each block is of 512 bytes) for(i = 0; i < ITERATIONS; i++){ s_t = rdtsc(); c = addr1[i + j*4*KB]; // read at multiple of page size,so every read causes a page fault j *= 2; e_t = rdtsc(); t += (e_t - s_t); } printf("Time required to service a page faut is %f \n",(t/ITERATIONS)/cpu_FREQ); munmap(addr1,SIZE_OF_MEMORY); munmap(addr2,SIZE_OF_MEMORY); return 0; }
我得到以下编译器警告:
lmelvix@Melvix:~/projects/mem$gcc mem1_4.c -lm mem1_4.c: In function ‘main’: mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] #define MB 1024 * KB ^ mem1_4.c:12:19: note: in expansion of macro ‘MB’ #define GB 1024 * MB ^ mem1_4.c:13:28: note: in expansion of macro ‘GB’ #define SIZE_OF_MEMORY 2 * GB // Main memory size ^ mem1_4.c:40:30: note: in expansion of macro ‘SIZE_OF_MEMORY’ addr1 = (char *) mmap(0,0); ^ mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] #define MB 1024 * KB ^ mem1_4.c:12:19: note: in expansion of macro ‘MB’ #define GB 1024 * MB ^ mem1_4.c:13:28: note: in expansion of macro ‘GB’ #define SIZE_OF_MEMORY 2 * GB // Main memory size ^ mem1_4.c:44:30: note: in expansion of macro ‘SIZE_OF_MEMORY’ addr2 = (char *) mmap(0,0); ^ mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] #define MB 1024 * KB ^ mem1_4.c:12:19: note: in expansion of macro ‘MB’ #define GB 1024 * MB ^ mem1_4.c:13:28: note: in expansion of macro ‘GB’ #define SIZE_OF_MEMORY 2 * GB // Main memory size ^ mem1_4.c:62:19: note: in expansion of macro ‘SIZE_OF_MEMORY’ munmap(addr1,SIZE_OF_MEMORY); ^ mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] #define MB 1024 * KB ^ mem1_4.c:12:19: note: in expansion of macro ‘MB’ #define GB 1024 * MB ^ mem1_4.c:13:28: note: in expansion of macro ‘GB’ #define SIZE_OF_MEMORY 2 * GB // Main memory size ^ mem1_4.c:63:19: note: in expansion of macro ‘SIZE_OF_MEMORY’ munmap(addr2,SIZE_OF_MEMORY); ^
当我用命令运行它时,我得到了错误
./a.out file1.txt file2.txt mmap: Cannot allocate memory
MAP_PRIVATE(以便其他进程不应访问此文件)和MAP_POPULATE(这样
当我们调用mmap()完成文件映射到内存中)以及PROT_READ保护标志.
首先我们映射file1,因为我们使用MAP_POPULATE完成RAM由对应于该文件的数据填充.在此之后,我们使用相同的标志映射file2,因此现在我们将file2完全映射到RAM中.因此,访问file1的数据将导致页面错误,因为file2占用了所有可用的RAM.我们还使用MADV_RANDOM标志设置调用madvise()系统调用,建议内核不要为两个文件执行提前读取页面.所以现在一旦这个初始设置完成,file2占用了所有可用的RAM,我们随机访问对应于file1的数据(以避免由内核执行的预读读取优化的任何影响,并且还避免从L3缓存读取)因为,RAM充满了对应于file2的数据,每次访问对应文件的数据都会导致页面错误.我们在循环中的映射区域上执行10个随机读数,并测量此操作所需的平均时间.
解决方法
看看你得到的编译器警告.你在这里有一个整数溢出:#define SIZE_OF_MEMORY 2 * GB.等于2 ^ 31 == 0b1000 … 0,对于signed int等于INT_MIN.这就是mmap失败的原因.
您应该在定义中使用unsigned literals:
#define KB (1024u) #define MB (1024u * KB) #define GB (1024u * MB) #define SIZE_OF_MEMORY (2u * GB)