Perl 中的线程同步/调度

发布于 2024-09-14 06:18:28 字数 643 浏览 2 评论 0原文

我有一个 perl 对象,其中有一些函数。每个函数从主程序中调用一次。我想并行运行一些函数以节省时间。我无法同时运行所有函数,因为某些函数依赖于先前函数的结果。

我想到了这样的事情:

  1. 对于每个函数,保留一个初始化为 false 的标志,并在函数结束时将其设置为 true (例如,func1 中的最后一行将是 $is_func1_done = 1 )。
  2. 用一个循环启动每个函数,该循环等待直到它所依赖的函数的所有标志都为 true。例如:如果 func1 依赖于 func2func3 则:

    <前><代码> sub func1 { while (!($is_func2_done && $is_func3_done)) { # 什么都不做 } # 做工作 }

那么我可以立即为每个函数启动一个线程,但每个函数的实际工作功能只有在准备就绪时才会启动。这有道理吗?我需要在旗帜上加锁吗?使用这样的 while 循环常见吗? -- 我想到了“忙等待”这个词……也许我的大部分 CPU 时间都会花在这些 while 上?有没有更标准的解决方案?

I have a perl object with a few functions in it. Each functions is called once from the main program. I would like to run some of the functions in parallel to save time. I can't run all of them together since some functions depend on the results of previous functions.

I thought of something like this:

  1. For each function keep a flag that is initialized to false and is set to true by the function when it ends (e.g. the last line in func1 would be $is_func1_done = 1).
  2. Start each function with a loop that waits until all the flags of the functions it depends on are true. For example: if func1 depends on func2 and func3 then:

     sub func1 {
      while (!($is_func2_done && $is_func3_done)) {
       # do nothing
      } 
      # do work
     }
    

Then I can start immediately a thread for each function, but the actual work of each function will start only when it's ready. Does this make sense? Do I need any locks here on the flags? Is using such while loops common? -- the term busy waiting comes to mind... maybe most of my CPU time will be spent on these whiles? Is there a more standard solution to this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沙与沫 2024-09-21 06:18:28

这有意义吗?

是的 - 每个任务都知道其先决条件,并在执行之前等待它们满足。它是众多有效设计之一,尽管您可能会发现随着任务数量的增加以及它们的相互依赖性变得更加复杂而难以扩展。

我需要在标志上加锁吗?

是的。这些标志需要共享,以便一个线程可以操作它们,另一个线程可以看到它,并且共享变量需要被 lock()ed 才能安全使用。

使用这样的 while 循环常见吗? -- 我想到了“忙碌等待”这个词

遗憾的是,是的,但是请不要这样做。 Perl 中的共享变量可以用作条件变量,线程可以通过它发送通知彼此之间:

sub func1 {
    {
        lock(%shared_state);
        until ($shared_state{ "func2 done" } and $shared_state{ "func3 done" }) {
            cond_wait(%shared_state);
        }
    }
    # do work -- note that %shared_state is unlocked

    # now tell others that we're done
    lock(%shared_state);
    $shared_state{ "func1 done" } = 1;
    cond_broadcast(%shared_state);
    # %shared_state will be unlocked, and broadcast delivered when we leave this scope
}

当您cond_wait时,共享变量将被解锁并且您的线程将进入睡眠状态。无需忙循环。

是否有更标准的解决方案?

$thr->join,如 Sinan 建议< /a> 是等待特定线程完成运行的一种简单而自然的方法。 Thread::Semaphore 可以提供类似但更复杂的功能(并且,有帮助的是,可以被初始化为小于零的值)。 “等待这 5 个线程完成某事”的常见需求可以通过 线程来实现: :屏障。 TMTOWTDI。

Does this make sense?

Yes - each task knows its preconditions, and waits for them to be met before executing. It's one of a number of valid designs, though you might find it difficult to scale as the number of tasks grow and their interdependencies grow more complex.

Do I need any locks here on the flags?

Yes. The flags need to be shared, so that one thread can manipulate them and another see it, and shared variables need to be lock()ed to be used safely.

Is using such while loops common? -- the term busy waiting comes to mind

Sadly yes, but Don't Do That, Please. Shared variables in perl can serve as condition variables through which threads can send notifications to one another:

sub func1 {
    {
        lock(%shared_state);
        until ($shared_state{ "func2 done" } and $shared_state{ "func3 done" }) {
            cond_wait(%shared_state);
        }
    }
    # do work -- note that %shared_state is unlocked

    # now tell others that we're done
    lock(%shared_state);
    $shared_state{ "func1 done" } = 1;
    cond_broadcast(%shared_state);
    # %shared_state will be unlocked, and broadcast delivered when we leave this scope
}

When you cond_wait, the shared variable is unlocked and your thread is put to sleep. No need to busy loop.

Is there a more standard solution to this?

$thr->join, as Sinan suggests, is an easy and natural way to wait for a specific thread to finish running. Thread::Semaphore can serve a similar but more complex function (and, helpfully, can be initialized to values less than zero). A common need to "wait for these 5 threads to finish something" can be achieved with a Thread::Barrier. TMTOWTDI.

烛影斜 2024-09-21 06:18:28

您应该使用 $thr->join 来等待线程完成。

例如:

#!/usr/bin/perl

use strict; use warnings;
use threads;

my @threads = map threads->create($_), qw( func1 func2 );
$_->join for @threads;

my $thr3 = threads->create('func3');
$thr3->join;

sub func1 {
    for (1 .. 5) {
        print "func1\n";
        sleep 1 + rand 3;
    }
    return;
}

sub func2 {
    for (1 .. 5) {
        print "func2\n";
        sleep 1 + rand 2;
    }
    return;
}

sub func3 {
    print "Time to do some work\n";
}

我不知道使用这样的 while 循环是否常见:我不会。

You should use $thr->join to wait for a thread to finish.

For example:

#!/usr/bin/perl

use strict; use warnings;
use threads;

my @threads = map threads->create($_), qw( func1 func2 );
$_->join for @threads;

my $thr3 = threads->create('func3');
$thr3->join;

sub func1 {
    for (1 .. 5) {
        print "func1\n";
        sleep 1 + rand 3;
    }
    return;
}

sub func2 {
    for (1 .. 5) {
        print "func2\n";
        sleep 1 + rand 2;
    }
    return;
}

sub func3 {
    print "Time to do some work\n";
}

I don't know if it is common to use such while loops: I would not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文