user-0 提问: 关于C语言IO输出txt的效率问题

回复:
user: user-1
content: 7楼已经给了你方法。

user: user-2
content: 引用 1 楼 zhao4zhong1 的回复:无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！  不要低估操作系统读写文件使用内存缓冲区优化速度时的智商。 赵四老师请教一个问题，现在公司有个项目要做多线程读写的功能，就是从多个存储设备读取数据写入到单个磁盘中，要求数据读取要多线程同步进行，但是考虑到磁盘实际是异步写入，如果多线程会不会导致磁盘频繁跳针，对磁盘损耗过大？有没有什么缓解的方法？

user: user-1
content: 学会使用profiler才是王道。

user: user-1
content: 建议换Intel的编译器再试试。

user: user-0
content: 引用 12 楼 qq_35359073 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] 没准只是因为fortran写的文件碎片少；而C写的文件碎片多罢了。 这是我写的fortran和C的代码对比，可能是我小白，C写的代码很垃圾； 都是windows764位的I5-6200的cpu环境下，假设3年，每年365天，有300个单元，每个单元（行）输出1个字符串+80个双精度浮点数； 这是C的，运行时间为20秒左右大约生成了200M的文件，VC编译后运行20秒左右，GCC编译后运行时间也是20秒左右 #include <stdio.h> #include <stdlib.h> #include <time.h>  int main(){ 	FILE *fp = NULL; 	char hruname[14] = {"test"}; 	int year = 0, day = 0, h = 0, i = 0; 	int start_time = 0, end_time = 0; 	double /*array[1000000] = {0.0},*/ run_time = 0.0; 	double *array = (double*)calloc(80, sizeof(double)); 	for (i = 0; i < 80; ++i) { 		array[i] = 5.0/* * random()*/; 	} 	start_time = clock(); 	fp = fopen("TEST.txt", "w");  	for (year = 0; year < 3; year++) 	{ 		for (day = 0; day < 365; day++) 		{ 			for (h = 0; h < 300; h++) 			{ 				fprintf(fp,"%8s", hruname);  				for(i = 0; i < 80; ++i) 				{ 					fprintf(fp,"%8.4lf", array[i]); 				} 			} 			fprintf(fp,"\n"); 		} 		printf("第%d年完毕\n", year); 	}  	fclose(fp); 	end_time = clock(); 	run_time = ((double)end_time - (double)start_time) / 1000.0; 	printf("%lf", run_time); 	getchar(); 	return 0; }   这是fortran的代码，使用visual studio2012平台和intel fortran2013编译器编译，运行时间为5.5秒左右！ program main     !初始化数据     real, dimension (:), allocatable :: array     real :: t, start_time, end_time     character (len=14) :: hruname     integer :: i, year, day , h     allocate (array(80))     array = 5.0     i = 0     year = 0     day = 0     h = 0     hruname = "test"     !生成随机数     !call random_seed()     !do i = 1, 100000     !    array(i) = 5.;     !end do     call CPU_TIME(start_time)     open (1,file="TEST.txt")     do year = 1, 3         do day = 1, 365             do h = 1, 300                 write(1,1001) hruname, (array(i), i = 1, 80)                               end do         end do         write(*,*) "年结束"     end do     close(1)     call CPU_TIME(end_time)     write(*,*) end_time - start_time     pause 1001 format(a8, 80f8.4)       stop end   我承认我很菜，但是请问在IO输出上，C和fortran的差距有这么大么？[/quote]  我又试了一下，fortran之所以能够快这么多，就是fortran的矩阵计算十分变态，如果write(1,1001) hruname (array(i), i = 1, 80)  这里不用隐式循环而改成                 do i = 1 , 80                     write(1,1003) array(i)                 end do 也是巨慢无比，要比C语言还慢好几倍，与隐式循环差了10倍！真希望C语言也能有这么强的数组运算能力！

user: user-0
content: 引用 11 楼 zhao4zhong1 的回复:没准只是因为fortran写的文件碎片少；而C写的文件碎片多罢了。 这是我写的fortran和C的代码对比，可能是我小白，C写的代码很垃圾； 都是windows764位的I5-6200的cpu环境下，假设3年，每年365天，有300个单元，每个单元（行）输出1个字符串+80个双精度浮点数； 这是C的，运行时间为20秒左右大约生成了200M的文件，VC编译后运行20秒左右，GCC编译后运行时间也是20秒左右 #include <stdio.h> #include <stdlib.h> #include <time.h>  int main(){ 	FILE *fp = NULL; 	char hruname[14] = {"test"}; 	int year = 0, day = 0, h = 0, i = 0; 	int start_time = 0, end_time = 0; 	double /*array[1000000] = {0.0},*/ run_time = 0.0; 	double *array = (double*)calloc(80, sizeof(double)); 	for (i = 0; i < 80; ++i) { 		array[i] = 5.0/* * random()*/; 	} 	start_time = clock(); 	fp = fopen("TEST.txt", "w");  	for (year = 0; year < 3; year++) 	{ 		for (day = 0; day < 365; day++) 		{ 			for (h = 0; h < 300; h++) 			{ 				fprintf(fp,"%8s", hruname);  				for(i = 0; i < 80; ++i) 				{ 					fprintf(fp,"%8.4lf", array[i]); 				} 			} 			fprintf(fp,"\n"); 		} 		printf("第%d年完毕\n", year); 	}  	fclose(fp); 	end_time = clock(); 	run_time = ((double)end_time - (double)start_time) / 1000.0; 	printf("%lf", run_time); 	getchar(); 	return 0; }   这是fortran的代码，使用visual studio2012平台和intel fortran2013编译器编译，运行时间为5.5秒左右！ program main     !初始化数据     real, dimension (:), allocatable :: array     real :: t, start_time, end_time     character (len=14) :: hruname     integer :: i, year, day , h     allocate (array(80))     array = 5.0     i = 0     year = 0     day = 0     h = 0     hruname = "test"     !生成随机数     !call random_seed()     !do i = 1, 100000     !    array(i) = 5.;     !end do     call CPU_TIME(start_time)     open (1,file="TEST.txt")     do year = 1, 3         do day = 1, 365             do h = 1, 300                 write(1,1001) hruname, (array(i), i = 1, 80)                               end do         end do         write(*,*) "年结束"     end do     close(1)     call CPU_TIME(end_time)     write(*,*) end_time - start_time     pause 1001 format(a8, 80f8.4)       stop end   我承认我很菜，但是请问在IO输出上，C和fortran的差距有这么大么？

user: user-1
content: 没准只是因为fortran写的文件碎片少；而C写的文件碎片多罢了。

user: user-3
content: 引用 4 楼 qq_35359073 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] 建议楼主试一下，不会你想像的那么慢。 再说你的要求只是100000次。 与其纸上谈兵，不如实际操作一下； IO是有缓存的，并且也不是你说的调一下fprintf就往文件里写一下，往磁盘写数据先放到缓存里，然后到一定数量了（达到一定字节数）才会真正的刷到文件里。你好，我试了一下，主要我想与fortran语言进行一下对比，感觉C语言在IO的输出上要比fortran满了太多，同样的输出量，C语言输出的时间是fortran的两倍！[/quote] 你用两种语言算一下用时，看那个用时时间长一些。把它们的分别用时打出来。

user: user-4
content: 引用 8 楼 qq_35359073 的回复:引用 5 楼 jianwen0529 的回复:请查看release版本的用时。release版本，同样写2G的数据（格式一样，fortran写的还稍微多一些）多次测试是fortran的用时为：90秒左右，C的用时是178秒左右 格式化（fprintf）写还是非格式化（write）写？是否每次写都有刷新输出流缓冲区的动作？

user: user-0
content: 引用 5 楼 jianwen0529 的回复:请查看release版本的用时。release版本，同样写2G的数据（格式一样，fortran写的还稍微多一些）多次测试是fortran的用时为：90秒左右，C的用时是178秒左右

user: user-1
content: 您是否希望迅速对您频繁使用的文件进行碎片整理？使用 Contig 优化单个的文件，或者创建连续的新文件。http://technet.microsoft.com/zh-cn/sysinternals/bb897428

user: user-1
content: 你 再试一次 换台电脑 重启电脑 …… 没准就不是所谓的两倍了。  在文件大小相同的前提下：  读刚读过的文件比头次读没读过的文件快  读转速快的硬盘上的文件比读转速慢的硬盘上的文件快  读没有磁盘碎片的文件比读有磁盘碎片的文件快  读文件不处理比边读边处理快  单线程从头到尾一次读文件比多线程分别读文件各部分快（非固态硬盘上）  读固态硬盘上的文件比读普通硬盘上的文件快 写类似。

user: user-4
content: 请查看release版本的用时。

user: user-0
content: 引用 2 楼 cfjtaishan 的回复:建议楼主试一下，不会你想像的那么慢。 再说你的要求只是100000次。 与其纸上谈兵，不如实际操作一下； IO是有缓存的，并且也不是你说的调一下fprintf就往文件里写一下，往磁盘写数据先放到缓存里，然后到一定数量了（达到一定字节数）才会真正的刷到文件里。你好，我试了一下，主要我想与fortran语言进行一下对比，感觉C语言在IO的输出上要比fortran满了太多，同样的输出量，C语言输出的时间是fortran的两倍！

user: user-0
content: 引用 1 楼 zhao4zhong1 的回复:无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！  不要低估操作系统读写文件使用内存缓冲区优化速度时的智商。你好，我试了一下，主要我想与fortran语言进行一下对比，感觉C语言在IO的输出上要比fortran满了太多，同样的输出量，C语言输出的时间是fortran的两倍！

user: user-3
content: 建议楼主试一下，不会你想像的那么慢。 再说你的要求只是100000次。 与其纸上谈兵，不如实际操作一下； IO是有缓存的，并且也不是你说的调一下fprintf就往文件里写一下，往磁盘写数据先放到缓存里，然后到一定数量了（达到一定字节数）才会真正的刷到文件里。

user: user-1
content: 无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！  不要低估操作系统读写文件使用内存缓冲区优化速度时的智商。