Когда слишком мало потоков, программа зависает - PullRequest
0 голосов
/ 08 января 2019

Когда следующая программа запускается для -t=17 -fn=15, программа останавливается в разумные сроки. Это означает, что максимальное количество потоков больше, чем количество файлов, которые записываются и одновременно кэшируются.

Обновление по запросу: вывод профилировщика , когда $ perl6 --profile con-test.p6 -t = 7 -fn = 5

Когда -t> = -fn, программа не может остановиться!

Когда программа запускается для -t=17 -fn=20 --hack, программа запускается до завершения в разумные сроки.

Я не знаю, происходит ли сбой нижеприведенной программы из-за того, что я сталкиваюсь с проблемой в CompUnit или существует проблема с потоком (или другой), которую я пропускаю.

Если предположить, что существует какая-то ситуация с потоками и что количество файлов должно быть меньше количества потоков, что будет лучшим способом переписать хак. В настоящее время массив заполнен Обещаниями, которые затем могут быть сохранены. Но ожидание требует, чтобы все они были сохранены перед очисткой массива и его повторным заполнением. Я думаю, что так или иначе это должно быть переписано как Канал или Поставка. Однако я не могу понять, как это сделать.

Заранее спасибо.

use v6.c;
use nqp;
use File::Directory::Tree;

my Lock $lock;
my $precomp;
#assume a writable directory files/

sub MAIN(:$t=5, :$fn = 10, :$hack=False ) {
    PROCESS::<$SCHEDULER> = ThreadPoolScheduler.new(initial_threads => 0, max_threads => $t);

    rmtree '.test';
    empty-directory 'files';

    my $precomp-store = CompUnit::PrecompilationStore::File.new(prefix => '.test'.IO );
    $precomp = CompUnit::PrecompilationRepository::Default.new(store => $precomp-store);
    $lock .=new;
    my %files = |gather for ^$fn {
        my $f = "files/name_$_.pod6";
        $f.IO.spurt: data;
        take "name_$_" => %(:key(nqp::sha1($f)), :path($f))
    }
    my @compilations;
    my @compiled;
    for %files.kv -> $source, (:path($path), :key($key)) {
        @compilations.push: start compile( $source, $key, $path );
        if $hack {
           if @compilations.elems %% ($t - 2) {
              @compiled.append: await @compilations;
              @compilations = ()
          }
       }
    }
    @compiled.append: await @compilations;
    for @compiled {
        if .<error>.defined {
            say .<error>
        }
        else {
            say .<source> ~ ' compiled'
        }
    }
}

sub compile( $source, $key, $path ) {
    my ($handle , $error, $status );
    try {
        CATCH {
            default {
                $error = "Compile error in $source:\n\t" ~ .Str
            }
        }
        $lock.protect( {
            $precomp.precompile($path.IO, $key, :force );
            $handle = $precomp.load($key)[0];
        })
    }
    with $handle {
        $status = 'OK';
    }
    else {
        $status = 'Failed';
        $error = 'unknown precomp error' without $error; # make sure that $error is defined for no handle
    }
    %(:$error, :$status, :$source)
}

sub data(-->Str ) {
    q:to/DD/
    =begin pod :tag<self>

    =TITLE Community
    X<|Community>

    =SUBTITLE Information about the people working on and using Perl 6

    =head1 Overview

    "Perl 5 was my rewrite of Perl.  I want Perl 6 to be the community's rewrite
    of Perl and of the community." - Larry Wall

    =head1 The Perl 6 community

    There is a large presence on the C<#perl6> channel on C<freenode.net>,
    who are happy to provide support and answer questions. More resources can be found in the L<perl6.org community page|https://perl6.org/community/>. L<Camelia|https://perl6.org/>, the multi-color butterfly with P 6 in her wings, is the symbol of this diverse and welcoming community. We use extensively
    the L<C<#perl6>|https://perl6.org/community/irc> IRC channel for communication, questions and simply hanging out. Check out this L<IRC lingo|http://www.ircbeginner.com/ircinfo/abbreviations.html> resource for the abbreviations frequently used there.  L<StackOverflow|https://stackoverflow.com/questions/tagged/perl6> is also a great resource for asking questions and helping others with their Perl 6 problems and challenges.

    The Perl 6 community publishes every December an L<Advent Calendar|https://perl6advent.wordpress.com/>, with Perl 6 tutorials every day until Christmas. Organization and assignment of days is done through the different Perl 6 channels and the L<Perl6/mu|https://github.com/perl6/mu> repository. If you want to participate, it starts organization by the end of October, so check out the channels above for that.

    =end pod

    DD
}

1 Ответ

0 голосов
/ 28 января 2019

Проблема в том, что если требуется слишком много потоков, то программа зависает, поэтому обходной путь заключается в создании очереди, выделении как можно большего количества потоков, а затем, когда процедура в каждом потоке завершается, она извлекает данные очередь.

Ниже я реализовал эту стратегию, и она обрабатывает, без заморозки, случай, когда количество потоков меньше, чем количество файлов. На самом деле количество потоков должно быть на два меньше количества файлов (см. if +@threads < $t - 2). Уменьшение от 2 до 1 вызывает зависание программы снова. Не совсем уверен, почему это так.

Ниже приведена перезапись программы с вопросом в очереди.

#!/usr/bin/env perl6
use v6.d;
use nqp;
use File::Directory::Tree;

my Lock $lock;
my $precomp;
#assume a writable directory files/

sub MAIN(:$t=15, :$fn = 10 ) {
    say "Threads: $t, Files: $fn, Compiler:", $*PERL;
    PROCESS::<$SCHEDULER> = ThreadPoolScheduler.new(initial_threads => 0, max_threads => $t);

    rmtree '.test';
    empty-directory 'files';

    my $precomp-store = CompUnit::PrecompilationStore::File.new(prefix => '.test'.IO );
    $precomp = CompUnit::PrecompilationRepository::Default.new(store => $precomp-store);
    $lock .=new;
    my %files = |gather for ^$fn {
        my $f = "files/name_$_.pod6";
        $f.IO.spurt: data;
        take "name_$_" => %(:key(nqp::sha1($f)), :path($f))
    }
    my @compilations;
    my @compiled;
    my @threads; 
    for %files.kv -> $source, (:path($path), :key($key)) {
        @compilations.push: ( $source, $key, $path );
        @threads.push( start
            sub ( @queue ) {
                my @params = @queue.pop.list if @queue;
                return unless +@params;
                my $res = compile( |@params );
                $lock.protect({
                    @compiled.append: $res;
                });
                &?ROUTINE( @queue )
            }( @compilations )
        )  if +@threads < $t - 2;
    }
    await @threads;
    for @compiled {
        if .<error>.defined {
            say .<error>
        }
        else {
            say .<source> ~ ' compiled'
        }
    }
}

sub compile( $source, $key, $path ) {
    my ($handle , $error, $status );
    try {
        CATCH {
            default {
                $error = "Compile error in $source:\n\t" ~ .Str
            }
        }
        $precomp.precompile($path.IO, $key, :force );
        $handle = $precomp.load($key)[0];
    }
    with $handle {
        $status = 'OK';
    }
    else {
        $status = 'Failed';
        $error = 'unknown precomp error' without $error; # make sure that $error is defined for no handle
    }
    %(:$error, :$status, :$source)
}

sub data(-->Str ) {
    q:to/DD/
    =begin pod :tag<self>

    =TITLE Community
    X<|Community>

    =SUBTITLE Information about the people working on and using Perl 6

    =head1 Overview

    "Perl 5 was my rewrite of Perl.  I want Perl 6 to be the community's rewrite
    of Perl and of the community." - Larry Wall

    =head1 The Perl 6 community

    There is a large presence on the C<#perl6> channel on C<freenode.net>,
    who are happy to provide support and answer questions. More resources can be found in the L<perl6.org community page|https://perl6.org/community/>. L<Camelia|https://perl6.org/>, the multi-color butterfly with P 6 in her wings, is the symbol of this diverse and welcoming community. We use extensively
    the L<C<#perl6>|https://perl6.org/community/irc> IRC channel for communication, questions and simply hanging out. Check out this L<IRC lingo|http://www.ircbeginner.com/ircinfo/abbreviations.html> resource for the abbreviations frequently used there.  L<StackOverflow|https://stackoverflow.com/questions/tagged/perl6> is also a great resource for asking questions and helping others with their Perl 6 problems and challenges.

    The Perl 6 community publishes every December an L<Advent Calendar|https://perl6advent.wordpress.com/>, with Perl 6 tutorials every day until Christmas. Organization and assignment of days is done through the different Perl 6 channels and the L<Perl6/mu|https://github.com/perl6/mu> repository. If you want to participate, it starts organization by the end of October, so check out the channels above for that.

    =end pod

    DD
}
...