多线程读一个大文件的效率问题

goodfood 2002-07-01 04:07:43
问题描述:

一个文件,每一行是一条固定格式的记录,大概有60多万行,50-60M左右,用多线程将所

有记录读出进行分析。但是发现50个线程和1个线程的效率差不多,速度提高在2-8秒波

动,甚至有时还不如1个线程的效率。

程序大致流程如下,请教各位,哪里是速度瓶颈??要如何改进??

//共享锁说明 保证每一个共享资源都有一个锁来保证共享;
rdfile_lock 读文件锁;
log_lock 日志文件锁;
errfile_lock 错误记录文件锁;
buf_lock 数据缓冲区锁;

...
lock(rdfile_lock)
根据每个线程在文件中的不同的起始地点定位文件指针fp;
fgets(record, record_len, fp);
if (feof(fp)) {
unlock(fdfile_lock);
thread_exit(...);
}
unlock(fdfile_lock);
...
分析record;
if (record错误) {
lock(errfile_lock);
write_error_record();
unlock(errfile_lock);
lock(log_lock);
写日志文件;
unlock(log_lock);
}
...(处理记录)
lock(buf_lock)
将处理后的记录放入缓冲区
unlock(buf_lock);
...

是不是因为加锁,解锁太多导致效率降低?
...全文
523 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
LeeMaRS 2002-07-02
  • 打赏
  • 举报
回复
呵呵.和你们系统部的同事联系一下吧.
线程的经典例子...我这里没有:(
至于线程的数量,如果能做到根据CPU资源的情况,动态增加或减少,可能会比较好.(当然做起来就困难得多了)
goodfood 2002-07-02
  • 打赏
  • 举报
回复
看过了,多谢 LeeMaRS 。

相信这些系统部得同事已经做得很好了。

有什么关于线程的经典的例子没有??

我想明白在一件事情中,线程是如何根据实际情况划分,又按怎样的比例来确定数目才是最好?



LeeMaRS 2002-07-02
  • 打赏
  • 举报
回复
呵呵,麻烦了.
你来这里看看:http://www.pchdd.com/tiroplot/00Q2/000625/

我觉得要用RAID,就要保证一个文件被分在几个硬盘上,这时候用多线程去读,效率就可以提高.
goodfood 2002-07-02
  • 打赏
  • 举报
回复
磁盘阵列做了的,但是到底瓶颈在哪里,我也不知道,估计在CPU,虽然有8个,

但是服务器是99年买的,说不定还是pentium pro。我们提过建议,换个服务器,

但客户眼一瞪:就换?!当年花了近1000万咧!!

头头给我的任务就是尽量优化我的code,我只是一个coder而已 :(
LeeMaRS 2002-07-02
  • 打赏
  • 举报
回复
你最好是用RAID磁盘阵列吧,几个磁盘并发处理,效率提高相当多。
goodfood 2002-07-02
  • 打赏
  • 举报
回复
就如各位所说:将各个任务用线程处理,那如果这样分配:

读记录 1个线程,分析记录 N个线程,处理记录 N个线程;

那么 瓶颈还是在读记录的时候,后面的消费者会因为缓冲池中的数据太少而

多处于阻塞状态。

PS :sixfour(玄武的翁) 大的东西都是由小的部分组成的,50M的文件没什么,

但是N个50M合起来就多了-我需要处理的是将近50G的数据。
grey_whp 2002-07-01
  • 打赏
  • 举报
回复
你用淤泥?在下面没有overlapped可用,否则会提升很多的哦!,这样,你可以将程序设计像overlapped一样来使用.另外在读取时,如果读入的数据太小的话,将cpu交给别的线程,当数据大的时候首先去解决数据传输的问题哦.让大家(线程)平衡一下.
N3t9h0st 2002-07-01
  • 打赏
  • 举报
回复
我没看懂他为什么要用线程.
LeeMaRS 2002-07-01
  • 打赏
  • 举报
回复
~~~~~我败了~~~~谁来帮我一把:)
zengpan_panpan 2002-07-01
  • 打赏
  • 举报
回复
LeeMaRS 呵呵,谁叫你用同步读啊?就象Sybase文档上说得清清楚楚,用异步IO可以大大提高效率。
step_by_step 2002-07-01
  • 打赏
  • 举报
回复
你程序的设计逻辑有问题,首先读文件的锁就没有必要用,那样的话你所有的线程都被同步了,效率肯定下降了!你可以在每个线程里面单独的打开文件,这样的话读文件锁就不用了。
还有你可以把分析纪录的线程分离开来和读文件的线程并行运行,提高速度。
sixfour 2002-07-01
  • 打赏
  • 举报
回复
才50,60兆的文件,用线程干什么?
这不是找罪受么?
LeeMaRS 2002-07-01
  • 打赏
  • 举报
回复
to goodfood : 谢谢关心:) 刚才已经吃过了.

to 楼上的 : 你这句话"单处理器系统上用线程不可能提高效率".我觉得不太合理.假如我读磁盘只占了40%的CPU资源,那么剩下的60%的CPU资源,如果拿去做运算,肯定可以提高效率.
zengpan_panpan 2002-07-01
  • 打赏
  • 举报
回复
你应该反复运行一下你的程序,这不是一个线程的问题,而是文件系统及其缓存的问题。缓存足够大的话,下一次运行肯定快得多,线程倒是平白无故增加调度负担。线程设计出来就主要就是为了有效利用多处理器,单处理器系统上用线程不可能提高效率。不过一般为了利用阻塞机制图省事,还是不少系统用线程。最明显的是unix上的sybase,oracle之类的大型系统为了效率都用多进程机制,apache 2.0使用线程不过是为了兼容更多机器,java用线程不过是因为线程是sun发明的,然而i386上的java,远远不如sparc上的java.
goodfood 2002-07-01
  • 打赏
  • 举报
回复
哎呀,我怎么没想到在线程内部再fopen呢,

boxban(boxban) 的办法可以试一下,看看是不是会出现LeeMaRS(小菜虎_水壶的仇人) 说的情况。

顺便问候大家一句:吃了么?

LeeMaRS 2002-07-01
  • 打赏
  • 举报
回复
to 楼上 : 你有没有考虑到这样一个问题 : 多线程分别读取不同位置的数据,你读一下,我读一下,结果磁盘的磁头要来回定位,反而不利于效率的提高.
boxban 2002-07-01
  • 打赏
  • 举报
回复
我并认为瓶颈的关键不在磁盘I/O,而在于你的设计逻辑:
多个线程对同一个文件的分段读访问完全可以不用同步。也就是说,每个线程获得自己的一个文件描述符,然后分别定位到不同的文件区段并分别执行各自的读操作,然后分析读到的数据。示意如下:
int main()
{
//get file length
//create N threads
section_size = file_length / N;
for(cur_section = 0; cur_section < N; cur_section++)
create_thread(thread_func, cur_section * section_size);

...

}
void* thread_func(void* arg)
{
int offset = (int)arg;
FILE* fp;

fp = fopen("..", "r");
fseek(fp, offset, SEEK_SET);
fread(...);
//...
}
LeeMaRS 2002-07-01
  • 打赏
  • 举报
回复
@_@ 这可麻烦了.

先看看我在网上看到的一句话 :

线程(Thread)的概念在一些以前的操作系统中是不存在的,例如以前的UNIX和Windows3.X .

然后我对Unix根本是一窍不通.

看来你得到别的版去问问了...
goodfood 2002-07-01
  • 打赏
  • 举报
回复
sorry, 我用的是unix
LeeMaRS 2002-07-01
  • 打赏
  • 举报
回复
要设置线程的优先级,可能要用到API函数了.(或者你应该看看MFC中是否有这个函数,我没学过MFC.SORRY.)

至于要用到什么API函数,你可以来这里:
http://chairman.3322.net/vbapi/course2.htm
看看.那个SetPriorityClass应该就是你想要的.
加载更多回复(8)

69,335

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧