Indeed, but the final death knell is that using a mirror structure of individual sems is 3 times slower than locking the entire hash!
Lock the hash:
#! perl -slw
use strict;
use Data::Dump qw[ pp ];
use Time::HiRes qw[ time ];
use List::Util qw[ shuffle ];
use threads;
use threads::shared;
our $START //= 'aaa';
our $END //= 'zzz';
my %hash :shared = map{ $_ => 0 } $START .. $END;
my $start = time;
$_->join for map{
async{
my @order;
{
lock %hash;
@order = shuffle keys %hash;
}
for ( @order ) {
lock %hash;
++$hash{ $_ };
}
}
} 1 .. 4;
printf "Lock hash took %.3f seconds\n", time() - $start;
my @fails = grep $_ != 4, values %hash;
warn @fails . " fails\n" if @fails;
__END__
C:\test>909437-1
Lock hash took 1.093 seconds
Locking scalars: #! perl -slw
use strict;
use Data::Dump qw[ pp ];
use Time::HiRes qw[ time ];
use List::Util qw[ shuffle ];
use threads;
use threads::shared;
our $START //= 'aaa';
our $END //= 'zzz';
my %sems :shared = map{ my $n :shared = 0; $_ => \$n } $START .. $END;
my %hash :shared = map{ $_ => 0 } $START .. $END;
my $start = time;
$_->join for map{
async{
my @order;
{
lock %hash;
@order = shuffle keys %hash;
}
for ( @order ) {
lock ${ $sems{ $_ } };
++$hash{ $_ };
}
}
} 1 .. 4;
printf "Lock scalars ref took %.3f seconds\n", time() - $start;
my @fails = grep $_ != 4, values %hash;
warn @fails . " fails\n" if @fails;
__END__
C:\test>909437-3
Lock scalars ref took 4.667 seconds
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
|