我有一个perl程序,它试图将一堆文件从一种格式转换为另一种格式(通过命令行工具)。它工作得很好,但是太慢了,因为它只在一次和一次转换文件。
我研究并使用了叉()机制,试图将所有的转换派生为子叉,希望能够利用cpu/内核。
编码是做和测试,它确实提高了性能,但没有达到我预期的方式。在查看/proc/cpuinfo时,我有以下内容:
> egrep -e "core id" -e ^physical /proc/cpuinfo|xargs -l2 echo|sort -u
physical id : 0 core id : 0
physical id : 0 core id : 1
physical id : 0 core id : 2
physical id : 0 core id : 3
physical id : 1 core id : 0
physical id : 1 core id : 1
physical id : 1 core id : 2
physical id : 1 core id : 3也就是说我有两个CPU和一个四核?如果是这样的话,我应该能够支付8个叉子,而且我应该可以做一个8分钟的工作(每个文件1分钟,8个文件)在1分钟内完成(8个叉子,每个叉子1个文件)。
然而,当我测试运行这个,它仍然需要4分钟才能完成。它似乎只使用了两个CPU,而不是核心?
因此,我的问题是:
增加:
我甚至尝试多次运行以下命令来模拟多个处理和监视htop。
while true; do echo abc >>devnull; done &不知何故htop告诉我我有16个核心?然后,当我产生4以上的时间循环,我看到其中4个使用了~100%的cpu每个。当我产生更多时,它们都开始平均地降低cpu利用率。(例如,8处理,参见htop中的8 bash,但使用大约50%)这是否意味着什么?
先谢了。我试过谷歌,但找不到一个明显的答案。
编辑: 2016-11-09
下面是perl代码的摘录。我很想看看我在这里做错了什么。
my $maxForks = 50;
my $forks = 0;
while(<CIFLIST>) {
extractPDFByCIF($cifNumFromIndex, $acctTypeFromIndex, $startDate, $endDate);
}
for (1 .. $forks) {
my $pid = wait();
print "Child fork exited. PID=$pid\n";
}
sub extractPDFByCIF {
# doing SQL constructing to for the $stmt to do a DB query
$stmt->execute();
while ($stmt->fetch()) {
# fork the copy/afp2web process into child process
if ($forks >= $maxForks) {
my $pid = wait();
print "PARENTFORK: Child fork exited. PID=$pid\n";
$forks--;
}
my $pid = fork;
if (not defined $pid) {
warn "PARENTFORK: Could not fork. Do it sequentially with parent thread\n";
}
if ($pid) {
$forks++;
print "PARENTFORK: Spawned child fork number $forks. PID=$pid\n";
}else {
print "CHILDFORK: Processing child fork. PID=$$\n";
# prevent child fork to destroy dbh from parent thread
$dbh->{InactiveDestroy} = 1;
undef $dbh;
# perform the conversion as usual
if($fileName =~ m/.afp/){
system("file-conversion -parameter-list");
} elsif($fileName =~ m/.pdf/) {
system("cp $from-file $to-file");
} else {
print ERRORLOG "Problem happened here\r\n";
}
exit;
}
# end forking
$stmt->finish();
close(INDEX);
}发布于 2016-11-09 12:06:34
fork()生成一个新进程--与现有进程相同,状态相同。不多也不差。内核对它进行调度,并在任何地方运行它。
如果您没有得到预期的结果,我会建议,一个更有可能的限制因素是,您正在从磁盘子系统读取文件--磁盘速度很慢,而对IO的争夺实际上并没有使它们更快--如果有相反的情况的话,因为它会强制额外的驱动器查找和不太容易的缓存。
具体而言:
1/不,fork()只会克隆你的进程。
[2]除非您想要将大部分算法重写为shell脚本,否则基本上没有意义。但没有真正的理由认为这会有什么不同。
要继续编辑,请执行:
system('file-conversion')看起来非常像一个基于IO的进程,它将受到磁盘IO的限制。你的cp也是如此。Parallel::ForkManager,它极大地简化了分叉位?https://stackoverflow.com/questions/40500013
复制相似问题