당신에게 성능을 비용되어있는 '비트'로 더 좋은 생각을 가지고시겠습니까?
이유 물어 - 성능 병목의 거룩한 삼위 일체의 일종있다 :
- CPU가 - 실제 작업은 프로세서에서 수행되는
- '활성'메모리 메모리 프로파일 대의 (크기 사용 가능한 RAM을 그리고 당신이 얼마나 개편하고 있는지).
- IO - 디스크로 데이터를 전송합니다.
종종 다른 것과 상충 될 수 있습니다. 조회 테이블을 생성하여 CPU 효율을 높일 수 있습니다.
map과 같은 연산은 제가 가까이에서보기 시작하는 것들입니다. map/sort/grep과 같은 것들은 매우 강력하지만 최적의 알고리즘보다 덜한 알고리즘을 사용할 가능성이 있습니다.
CPU를 사용하는 경우 멀티 스레드 또는 포킹을 사용해 CPU 액세스를 늘릴 수 있습니다. 그것의면에서, 은 'matrix.txt'(예 : 각 줄은 독립 실행 형) 처리에 의존하지 않으므로으로 보입니다. 따라서 병렬 처리를위한 좋은 후보가 될 수 있습니다.
나는 Parallel :: ForkManager를 사용하여 루프를 while
루프로 감싸고 있다고 생각할 것입니다. 이 작업의 단점은 출력을 결정적으로 정렬하지 않아 주소 지정이 필요한 것입니다.이 작업을 하겠지만, 당신은 거의 확실 원하지 무엇을 임의의 출력 순서를 얻을 것이다 -
use List::Util 'sum';
use Data::Dumper;
use Fcntl qw(:flock);
use Parallel::ForkManager;
my $mgr = Parallel::ForkManager->new(10);
my @indexes = do {
open my $fh, '<', "INPUT.txt";
map {
[ map { $_ - 1 } split ' ' ]
} <$fh>;
};
open my $infh, '<', "matrix.txt";
open my $out_fh, '>', "output.txt";
while (<$infh>) {
$mgr->start and next;
my @vals = split ' ';
my $output_line = join(' ', map { sum(@vals[@$_]) } @indexes),
"\n";
{
flock($out_fh, LOCK_EX);
print {$out_fh} $output_line;
}
}
close $out_fh;
참고 :
그래서 10 스타터 수 있습니다. 그러나 'join/map/sum'작업을 수행하는 데 동시에 10 개의 프로세서가 사용됩니다.
(물론 IO 바인딩을 사용하는 경우에는 도움이되지 않습니다.) 예를 들어
use warnings;
use strict;
use List::Util 'sum';
use threads;
use Thread::Queue;
my $line_q = Thread::Queue -> new();
my $output_q = Thread::Queue -> new();
my %line_output : shared;
my @indexes = do {
open my $fh, '<', "INPUT.txt";
map {
[ map { $_ - 1 } split ' ' ]
} <$fh>;
};
sub generate_output {
while (my $item = $line_q -> dequeue()) {
print "processing $item \n";
my ($line_num, @vals) = split (' ', $item);
$output_q -> enqueue($line_num.":". join(' ', map {sum(@vals[@$_])} @indexes). "\n");
}
}
sub coalesce_output {
open my $out_fh, '>', "output.txt";
my $current_line = 0;
my %lines;
while (my $item = $output_q -> dequeue) {
my ($line_num, $output_line) = split (":", $item);
if ($line_num = $current_line) {
print {$out_fh} $output_line;
$current_line++;
}
else {
$lines{$line_num} = $output_line;
}
while (defined $lines{$current_line}) {
print {$out_fh} $lines{$current_line};
delete $lines{$current_line};
$current_line++;
}
}
}
open my $infh, '<', "matrix.txt";
my @workers;
for (1..10) {
push (@workers, threads -> create (\&generate_output));
}
threads -> create (\&coalesce_output);
while (my $line = <$infh>) {
$line_q -> enqueue ("$.: $line");
}
$line_q -> end();
foreach my $thr (@workers) {
$thr -> join();
}
$output_q -> end();
:
는하지만 IO를 동기화, 나는 스레딩 아주 좋은 방법입니다 찾을 수 있습니다. 합계 작업을 병렬로 수행하려면 10 명의 작업자를, 올바른 순서로 데이터를 쓰려면 하나의 '출력'스레드를 돌립니다.
그래서 같은 :
use warnings;
use strict;
use List::Util 'sum';
use threads;
use Thread::Queue;
my $line_q = Thread::Queue->new();
my $output_q = Thread::Queue->new();
my @indexes = do {
open my $fh, '<', "INPUT.txt";
map {
[ map { $_ - 1 } split ' ' ]
} <$fh>;
};
sub generate_output {
while (my $item = $line_q->dequeue()) {
#print "processing $item \n";
my ($line_num, @vals) = split(' ', $item);
$output_q->enqueue($line_num . ":"
. join(' ', map { sum(@vals[@$_]) } @indexes)
. "\n");
}
}
sub coalesce_output {
open my $out_fh, '>', "output.txt";
my $current_line = 1;
my %lines;
while (my $item = $output_q->dequeue) {
my ($line_num, $output_line) = split(":", $item);
# print "Got $line_num ($current_line) $item\n";
if ($line_num = $current_line) {
# print "printing $current_line = $output_line\n";
print {$out_fh} $output_line;
$current_line++;
}
else {
$lines{$line_num} = $output_line;
}
while (defined $lines{$current_line}) {
# print "printing (while) $current_line = $lines{$current_line}\n";
print {$out_fh} $lines{$current_line};
delete $lines{$current_line};
$current_line++;
}
}
}
open my $infh, '<', "matrix.txt";
my @workers;
for (1 .. 40) {
push(@workers, threads->create(\&generate_output));
}
threads->create(\&coalesce_output);
while (my $line = <$infh>) {
$line_q->enqueue("$. $line");
}
$line_q->end();
foreach my $thr (@workers) {
$thr->join();
}
$output_q->end();
foreach my $thr (threads -> list) { $thr -> join(); }
는 (+ 이상) 생산 : 결국
1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
을하지만 - 그것은 당신의 제한 요인이 무엇인지에 다소 의존한다. 신속하고 더러운 테스트를 실행
는
Started at 1417007048,
finished at 1417007064
Took:16s
대를 제공합니다
Started at 1417007118
finished at 1417007161
Took:43s
가 보는
당신이 당신의 input.txt를 (그리고 matrix.txt) – osirisgothra
@osirisgothra 입력에 대한 링크를 삭제할 수있는 방법이있다 : https://www.dropbox.com/s/48ikhnfs7gzk8vm/input.txt은? dl = 0 매트릭스 : https://www.dropbox.com/s/ebxi608eday9z1e/matrix.txt?dl=0 – BioDeveloper
프로그램 프로필을 작성 했습니까? 그렇지 않다면 [Devel :: NYTProf] (https://metacpan.org/pod/Devel::NYTProf)를 시도하여 병목 현상이 무엇인지 확인하십시오. 또한, 귀하의 문제는 [PDL] (https://metacpan.org/pod/PDL)의 적절한 작업 인 것으로 보입니다.그것은 읽기 어렵습니다, 비슷한 일이 앞당겨지는 것을 본다면 잠시 가치가있을 것입니다. 의존성으로'Module :: Compile'을 가지고 있으며, 가장 최신 버전의 모듈은 많은 시스템에서 테스트를 통과하지 못합니다. 대부분의 시스템에서 동작하는 버전을 얻으려면'cpanm Module :: Compile @ 0.30'과 같이 설치하십시오. –