[Cascavel-pm] threads e uso de CPU
Alceu R. de Freitas Jr.
glasswalk3r em yahoo.com.br
Quarta Dezembro 9 15:29:22 PST 2009
Olá monges,
Estou utilizando o código abaixo para rodar tarefas em paralelo:
<code>
use warnings;
use strict;
use DBI;
use Text::LevenshteinXS qw(distance);
use Benchmark qw(timediff timestr);
use Term::ProgressBar;
use threads;
use threads::shared;
my $t0 = Benchmark->new();
my %contacts : shared;
my @con_list : shared;
my $minimum_score : shared = 85;
my $maximum_threads = 6;
my @threads;
get_db_data();
my @control = @con_list;
my $item;
print 'Starting processing data with maximum of ', $maximum_threads, ' threads', "\n";
my $progress = Term::ProgressBar->new(
{ name => 'Find Duplicated', count => scalar(@control) } );
my $total_processed = 0;
while (@control) {
$maximum_threads = scalar(@control)
if ( scalar(@control) < $maximum_threads );
my $i;
for ( $i = 1 ; $i <= $maximum_threads ; $i++ ) {
$threads[$i] = create_thread( "result_$i.txt", ( shift(@control) ) );
}
for ( $i = 1 ; $i <= $maximum_threads ; $i++ ) {
my ($found) = $threads[$i]->join();
#print "thread $i found $found" if ($found > 0);
}
$total_processed += $i;
$progress->update($total_processed);
}
$progress->update($total_processed);
my $t1 = Benchmark->new();
my $td = timediff( $t1, $t0 );
print 'the code took:', timestr($td), "\n";
sub create_thread {
my $file = shift;
my $contact = shift;
my $trh1 = threads->new( \&validate_contact, $file, $contact );
}
sub validate_contact {
my $file = shift;
my $item = shift;
my $counter = 0;
open( OUT, '>>', $file ) or die "Cannot create $file: $!\n";
my $source_name = $contacts{$item}->[0] . ' ' . $contacts{$item}->[1];
foreach my $contact (@con_list) {
#PERSON_UID is the same
next if $item eq $contact;
my $dest_name =
$contacts{$contact}->[0] . ' ' . $contacts{$contact}->[1];
my $dest_len = length($dest_name);
$dest_len = 1 unless ( $dest_len > 0 );
my $distance = distance( $source_name, $dest_name );
my $score = 100 - ( ( $distance * 100 ) / $dest_len );
# how much equal is the current row with the original one
if ( $score >= $minimum_score ) {
# source FST_NAME|LAST_NAME|CON_CD|PERSON_UID
print OUT $contacts{$item}->[0], '|', $contacts{$item}->[1],
'|',
$contacts{$item}->[2], '|', $item, '|';
# dest FST_NAME|LAST_NAME|CON_CD|PERSON_UID|SCORE
print OUT $contacts{$contact}->[0], '|',
$contacts{$contact}->[1],
'|', $contacts{$contact}->[2], '|', $contact, '|', $score,
"\n";
$counter++;
}
}
close(OUT);
return $counter;
}
sub get_db_data {
print 'Fetching contacts from database... ';
my $user = 'TESTE';
my $password = 'TESTE';
my $DSN = 'TESTE';
my $dbh =
DBI->connect( 'dbi:ODBC:' . $DSN, $user, $password, { RaiseError => 1 } )
or die "Database connection not made: $DBI::errstr";
my $query = q(
SELECT FST_NAME, LAST_NAME, PERSON_UID, CON_CD FROM CONTACT
ORDER BY FST_NAME, LAST_NAME
);
my $sth = $dbh->prepare($query);
$sth->execute();
while ( my $data = $sth->fetchrow_hashref() ) {
# avoid warnings
$data->{FST_NAME} = '' unless ( defined( $data->{FST_NAME} ) );
$data->{LAST_NAME} = '' unless ( defined( $data->{LAST_NAME} ) );
$data->{CON_CD} = '' unless ( defined( $data->{CON_CD} ) );
my @temp : shared =
( $data->{FST_NAME}, $data->{LAST_NAME}, $data->{CON_CD} );
$contacts{ $data->{PERSON_UID} } = \@temp;
push( @con_list, $data->{PERSON_UID} );
}
$sth->finish();
$dbh->disconnect() or warn $dbh->errstr;
print "OK\n";
}
</code>
O código executa normalmente, exceto pelo fato que mais lento do que eu gostaria. Otimizações à parte (como remover registros do hash depois de processados, algo que ainda não fiz) eu percebi que o computador aonde estou rodando isso (Intel Core2 DUO) não usa toda a capacidade de CPU (memória não é gargalo aqui). Ela fica entre 60 e 70% de uso. Eu gostaria que ficasse em algo como 90%, mas mesmo aumentando o número de threads simultâneas esse percentual não muda (e suspeito que o programa não vai rodar mais rápido por isso). Esse é um comportamento normal de se trabalhar com threads? É a primeira vez que uso isso com Perl.
Apesar de ler sobre recomendações de não usar threads com Perl, estou em um ambiente Microsoft e gostaria de alternativas simples de compartilhar dados em memória com execuções paralelas. Fico aberto à sugestões.
Abraços,
Alceu Rodrigues de Freitas Junior
--------------------------------------
glasswalk3r em yahoo.com.br
---
A well-used door needs no oil on its hinges.
A swift-flowing stream does not grow stagnant.
Neither sound nor thoughts can travel through a vacuum.
Software rots if not used.
These are great mysteries -- The Tao Of Programming, 5.1
____________________________________________________________________________________
Veja quais são os assuntos do momento no Yahoo! +Buscados
http://br.maisbuscados.yahoo.com
Mais detalhes sobre a lista de discussão Cascavel-pm