首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >perl叉()似乎没有利用核心,但只使用cpu。

perl叉()似乎没有利用核心,但只使用cpu。
EN

Stack Overflow用户
提问于 2016-11-09 03:58:02
回答 1查看 504关注 0票数 1

我有一个perl程序,它试图将一堆文件从一种格式转换为另一种格式(通过命令行工具)。它工作得很好,但是太慢了,因为它只在一次和一次转换文件。

我研究并使用了叉()机制,试图将所有的转换派生为子叉,希望能够利用cpu/内核。

编码是做和测试,它确实提高了性能,但没有达到我预期的方式。在查看/proc/cpuinfo时,我有以下内容:

代码语言:javascript
复制
> 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,而不是核心?

因此,我的问题是:

  1. perl的fork()只基于CPU而不是核心并行,这是真的吗?或者我做得不对?我只是使用了叉子()和wait()。没有什么特别事情。
  2. 我假设Perl的fork()应该使用内核,我是否可以编写一个简单的bash/perl来证明我的操作系统(即RedHat 4),或者Perl是导致这种症状的罪魁祸首?

增加:

我甚至尝试多次运行以下命令来模拟多个处理和监视htop。

代码语言:javascript
复制
while true; do echo abc >>devnull; done &

不知何故htop告诉我我有16个核心?然后,当我产生4以上的时间循环,我看到其中4个使用了~100%的cpu每个。当我产生更多时,它们都开始平均地降低cpu利用率。(例如,8处理,参见htop中的8 bash,但使用大约50%)这是否意味着什么?

先谢了。我试过谷歌,但找不到一个明显的答案。

编辑: 2016-11-09

下面是perl代码的摘录。我很想看看我在这里做错了什么。

代码语言:javascript
复制
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);
}
EN

回答 1

Stack Overflow用户

发布于 2016-11-09 12:06:34

fork()生成一个新进程--与现有进程相同,状态相同。不多也不差。内核对它进行调度,并在任何地方运行它。

如果您没有得到预期的结果,我会建议,一个更有可能的限制因素是,您正在从磁盘子系统读取文件--磁盘速度很慢,而对IO的争夺实际上并没有使它们更快--如果有相反的情况的话,因为它会强制额外的驱动器查找和不太容易的缓存。

具体而言:

1/不,fork()只会克隆你的进程。

[2]除非您想要将大部分算法重写为shell脚本,否则基本上没有意义。但没有真正的理由认为这会有什么不同。

要继续编辑,请执行:

  • system('file-conversion')看起来非常像一个基于IO的进程,它将受到磁盘IO的限制。你的cp也是如此。
  • 您是否考虑过Parallel::ForkManager,它极大地简化了分叉位?
  • 作为一个较小的风格点,您可能应该使用3 arg 'open‘。 #!/usr/bin/env使用严格;使用警告;使用并行::ForkManager;我的$maxForks = 50;我的$manager =并行::ForkManager->new($maxForks);而($ciflist) { ##使用$_进行解析。##instead of: extractPDFByCIF($cifNumFromIndex,$acctTypeFromIndex,$startDate,$endDate);#执行SQL构造,以便$stmt执行DB查询$stmt->execute();同时( $stmt->fetch() ){#叉复制/afp2web进程到子进程$manager->start和next;打印"CHILDFORK:处理子叉“。PID=$$\n";#防止子叉从父线程$ dbh ->{InactiveDestroy} =1破坏dbh;undef $dbh;#像往常一样执行转换,如果( $fileName =~ m/..afp/){system(“文件转换-参数列表”);} elsif ( $fileName =~ m/..pdf/){ system("cp $ from -file $ to -file");}{打印ERRORLOG“问题发生在这里\r\n”;}#结束分叉$manager->finish;} $stmt->finish();} $manager->wait_all_children;
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40500013

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档