我的第一个循环读取一些大文本文件并计算行/行.
在malloc之后,第二个循环填充分配的矩阵.
如果第二个循环被注释掉,则第一个循环需要1.5秒.但是,使用第二个循环进行编译会减慢第一个循环,现在需要30-40秒!
换句话说:第二个循环以某种方式减慢了第一个循环.我试图改变范围,更改编译器,更改编译器标志,更改循环本身,将所有内容放入main(),使用boost :: iostream甚至在共享库中放置一个循环,但在每次尝试中都会出现同样的问题!
第一个循环很快,直到用第二个循环编译程序.
编辑:这是我的问题的完整示例————>
#include <iostream> #include <vector> #include "string.h" #include "boost/chrono.hpp" #include "sys/mman.h" #include "sys/stat.h" #include "fcntl.h" #include <algorithm> unsigned long int countLines(char const *fname) { static const auto BUFFER_SIZE = 16*1024; int fd = open(fname,O_RDONLY); if(fd == -1) { std::cout << "Open Error" << std::endl; std::exit(EXIT_FAILURE); } posix_fadvise(fd,1); char buf[BUFFER_SIZE + 1]; unsigned long int lines = 0; while(size_t bytes_read = read(fd,buf,BUFFER_SIZE)) { if(bytes_read == (size_t)-1) { std::cout << "Read Failed" << std::endl; std::exit(EXIT_FAILURE); } if (!bytes_read) break; int n; char *p; for(p = buf,n=bytes_read ; n > 0 && (p = (char*) memchr(p,'\n',n)) ; n = (buf+bytes_read) - ++p) ++lines; } close(fd); return lines; } int main(int argc,char *argv[]) { // initial variables int offset = 55; unsigned long int rows = 0; unsigned long int cols = 0; std::vector<unsigned long int> dbRows = {0,0}; std::vector<std::string> files = {"DATA/test/file1.csv",// large files: 3Gb "DATA/test/file2.csv",// each line is 55 chars long "DATA/test/file3.csv"}; // find each file's number of rows for (int x = 0; x < files.size(); x++) { // <--- FIRST LOOP ** dbRows[x] = countLines(files[x].c_str()); } // define matrix row as being the largest row found // define matrix col as being 55 chars long for each csv file std::vector<unsigned long int>::iterator maxCount; maxCount = std::max_element(dbRows.begin(),dbRows.end()); rows = dbRows[std::distance(dbRows.begin(),maxCount)]; // typically rows = 72716067 cols = dbRows.size() * offset; // cols = 165 // malloc required space (11998151055) char *syncData = (char *)malloc(rows*cols*sizeof(char)); // fill up allocated memory with a test letter char t[]= "x"; for (unsigned long int x = 0; x < (rows*cols); x++) { // <--- SECOND LOOP ** syncData[x] = t[0]; } free(syncData); return 0; }
我还注意到,降低列数会加快第一个循环的速度.
探查器将手指指向此行:
while(size_t bytes_read = read(fd,BUFFER_SIZE))
该程序在此行上空闲30秒或等待计数为230,000.
在汇编中,等待计数发生在:
Block 5: lea 0x8(%rsp),%rsi mov %r12d,%edi mov $0x4000,%edx callq 0x402fc0 <------ stalls on callq Block 6: mov %rax,%rbx test %rbx,%rbx jz 0x404480 <Block 18>
我的猜测是从流中读取时出现了一个API块,但我不知道为什么?
解决方法
分配和触摸所有内存会从磁盘缓存中清除大文件,因此下一次运行必须从磁盘读取它们.
如果你运行没有loop2的版本几次来预热磁盘缓存,那么运行一个带有loop2的版本,我预测它会在第一次运行时很快,但是进一步运行会很慢,而不会再次预热磁盘缓存.
读取文件后会发生内存消耗.这会导致页面缓存(也称为磁盘缓存)上的“内存压力”,导致它从缓存中逐出数据,以便为进程写入的页面腾出空间.
您的计算机可能只有足够的可用RAM来缓存您的工作集.关闭您的Web浏览器可能会释放足够的空间来发挥作用!或者不是,因为您的11998151055是11.1GiB,并且您正在编写它的每一页. (每个字节,甚至.你可以用memset来实现更高的性能,虽然我假设你所展示的只是一个虚拟版本)
BTW,调查这个的另一个工具是时间./a.out.它可以显示您的程序是否将所有cpu时间花费在用户空间与内核(“系统”)时间上.
如果用户sys加起来实时,则您的进程受cpu限制.如果没有,它的I / O绑定,并且您的进程在磁盘I / O上阻塞(这是正常的,因为计算换行应该很快).