Perl-Threads, Variablen teilen

Perl-Threads, Variablen teilen

am 07.06.2006 01:38:38 von Torsten Mohr

Hallo,

ich möchte in einem Skript Daten zwischen dem Hauptprogramm
und einem Thread teilen (beide können Lesen und Schreiben
und Ändern). Dabei geht es hauptsächlich um eine relativ
komplexe Struktur (Ref auf Array aus Refs auf Hashes).

Momentan verwende ich "threads" und "threads::shared",
sehe aber keine vernünftige Möglichkeit, alle Teile der
Struktur über threads::shared als gemeinsam zu kennzeichnen.

In der Doku zu "Thread" habe ich gelesen daß bei diesem
Modell alle Daten per default gemeinsam verwendet werden
können.

Um das zu testen habe ich das unten angehängte Skript geschrieben,
es sieht aber nicht so aus, als ob sich der Wert von $a bzw.
der Inhalt von $r im Thread jemals ändert.


Kann mir jemand dazu einen Tipp geben?

Insgesamt suche ich eine Möglichkeit aus einem Hauptprogramm
und aus einem Thread lesend/schreibend/ändernd/löschend
auf eine tiefe Datenstruktur zuzugreifen.

Ein Tipp hierzu wäre auch prima.


Grüße,
Torsten.


#! /usr/bin/perl -w

use Thread;

$r = [];
$a = 0;

my $t = Thread->new(\&thr);

while($a < 10) {
$a++;
push(@$r, {val => $a});
print "main a $a r $r\n";

foreach my $v (@$r) {
print " - $$v{val}";
}
print "\n";

sleep 1;
}
sleep 2;


sub thr {
my $k;

while($a < 10) {
print "thread: a $a\n";
foreach my $v (@$r) {
print " $$v{val}";
}
print "\n";

sleep 1;
}
}

Re: Perl-Threads, Variablen teilen

am 07.06.2006 09:56:45 von Ch Lamprecht

Torsten Mohr schrieb:
> Hallo,
>
> ich möchte in einem Skript Daten zwischen dem Hauptprogramm
> und einem Thread teilen (beide können Lesen und Schreiben
> und Ändern). Dabei geht es hauptsächlich um eine relativ
> komplexe Struktur (Ref auf Array aus Refs auf Hashes).
>
> Momentan verwende ich "threads" und "threads::shared",
> sehe aber keine vernünftige Möglichkeit, alle Teile der
> Struktur über threads::shared als gemeinsam zu kennzeichnen.

Wenn du die Struktur schon zu Beginn kennst geht es so:
(oder ist das 'unvernünftig'?)

Christoph


#!/usr/bin/perl
use strict;
use warnings;

use threads;
use threads::shared;

my $a = 0;
share $a;
my $r = &share([]);
my $t = threads->create(\&thr);
push @$r, &share({}) for (0..9);

while ($a < 10) {

$r->[$a]{val}= $a;
print "main a $a \n";

foreach my $v (@$r) {
my $val = defined($v->{val})? $v->{val}:'';
print $val," - ";
}
print "\n";

sleep 1;
$a++;
}
sleep 2;


sub thr {
my $k;

while ($a < 10) {
print "thread: a $a\n";
foreach my $v (@$r) {
my $val = defined($v->{val})? $v->{val}:'';
print $val," - ";
}
print "\n";

sleep 1;
}
}


--

perl -e "print scalar reverse q/ed.enilno@ergn.l.hc/"

Re: Perl-Threads, Variablen teilen

am 07.06.2006 12:44:44 von Torsten Mohr

Hallo,

> Wenn du die Struktur schon zu Beginn kennst geht es so:
> (oder ist das 'unvernünftig'?)

danke für den Tip, werd ich mal ausprobieren.

Ich kenne die Struktur "im Prinzip". Ich weiß auf beiden Seiten
daß es sich um ein Array aus Hashes handelt. Um allerdings alle
Werte zu teilen muß ich das Array, jedes einzelne Hash und jeden
Wert innerhalb des Hash als "shared" markieren, vorausgesetzt ich
verwende threas und threads::shared.
Das meinte ich mit "vernünftig" und finde es sehr aufwändig.

Deshalb wollte ich "Thread" verwenden weil in der Doku dort steht
daß bei diesem Modell alle Variablen per "default" geteilt sind.
Das hat sich in meinem Beispiel allerdings nicht so Verhalten,
was ich noch nicht verstehe.

Meine aktuelle 'Lösung' sieht so aus daß ich drei geteilte Variablen
$lock_access, $main_changed, $thread_changed zur Synchronisation
verwende und die Datenstruktur mit Data::Dumper in eine Datei schreibe.
Von der jeweils anderen Seite lese ich den Inhalt wieder aus und per
"eval $content" ist er dann verfügbar.
Das gefällt mir so nicht sehr, aber da ich die Daten sowieso auf
Platte speichern muß habe ich gleich zwei Fliegen mit einer Klappe
erschlagen.


Grüße,
Torsten.


>
> Christoph
>
>
> #!/usr/bin/perl
> use strict;
> use warnings;
>
> use threads;
> use threads::shared;
>
> my $a = 0;
> share $a;
> my $r = &share([]);
> my $t = threads->create(\&thr);
> push @$r, &share({}) for (0..9);
>
> while ($a < 10) {
>
> $r->[$a]{val}= $a;
> print "main a $a \n";
>
> foreach my $v (@$r) {
> my $val = defined($v->{val})? $v->{val}:'';
> print $val," - ";
> }
> print "\n";
>
> sleep 1;
> $a++;
> }
> sleep 2;
>
>
> sub thr {
> my $k;
>
> while ($a < 10) {
> print "thread: a $a\n";
> foreach my $v (@$r) {
> my $val = defined($v->{val})? $v->{val}:'';
> print $val," - ";
> }
> print "\n";
>
> sleep 1;
> }
> }
>
>

Re: Perl-Threads, Variablen teilen

am 07.06.2006 21:03:19 von Slaven Rezic

Torsten Mohr writes:

> Hallo,
>
> > Wenn du die Struktur schon zu Beginn kennst geht es so:
> > (oder ist das 'unvernünftig'?)
>
> danke für den Tip, werd ich mal ausprobieren.
>
> Ich kenne die Struktur "im Prinzip". Ich weiß auf beiden Seiten
> daß es sich um ein Array aus Hashes handelt. Um allerdings alle
> Werte zu teilen muß ich das Array, jedes einzelne Hash und jeden
> Wert innerhalb des Hash als "shared" markieren, vorausgesetzt ich
> verwende threas und threads::shared.
> Das meinte ich mit "vernünftig" und finde es sehr aufwändig.
>
> Deshalb wollte ich "Thread" verwenden weil in der Doku dort steht
> daß bei diesem Modell alle Variablen per "default" geteilt sind.
> Das hat sich in meinem Beispiel allerdings nicht so Verhalten,
> was ich noch nicht verstehe.

Das alte Threading-Modell (das, was du in der Thread-Dokumentation
gelesen hast) hat sich als instabil erwiesen und wurde letztendlich
aufgegeben. Die jetztige Perl-Implementation ist einfach nicht
geeignet dafür.

Das neue Threading-Modell teilt nichts, sondern man muss tatsächlich
threads::shared für geteilte Variablen verwenden. Dieses ist nicht
sonderlich attraktiv, weil es nur relativ flache Strukturen verwalten
kann und (jedenfalls das letzte Mal, als ich es noch ausprobiert
hatte) nicht einmal mit Objekten umgehen kann.

> Meine aktuelle 'Lösung' sieht so aus daß ich drei geteilte Variablen
> $lock_access, $main_changed, $thread_changed zur Synchronisation
> verwende und die Datenstruktur mit Data::Dumper in eine Datei schreibe.
> Von der jeweils anderen Seite lese ich den Inhalt wieder aus und per
> "eval $content" ist er dann verfügbar.
> Das gefällt mir so nicht sehr, aber da ich die Daten sowieso auf
> Platte speichern muß habe ich gleich zwei Fliegen mit einer Klappe
> erschlagen.

Wenn du es einen Tick schneller haben willst, kannst du auch Storable
verwenden. Für einen Benchmark-Vergleich siehe auch hier:
http://idisk.mac.com/christian.hansen/Public/perl/serialize. pl

Man könnte die Ausgabe der Serializer auch in einer Perl-Variablen
speichern und nur diese mit threads::shared teilen...

Gruß,
Slaven

--
Slaven Rezic - slaven rezic de

Berlin Perl Mongers - http://berlin.pm.org

Re: Perl-Threads, Variablen teilen

am 07.06.2006 22:34:04 von Torsten Mohr

Hallo,

> Das neue Threading-Modell teilt nichts, sondern man muss tatsächlich
> threads::shared für geteilte Variablen verwenden. Dieses ist nicht
> sonderlich attraktiv, weil es nur relativ flache Strukturen verwalten
> kann und (jedenfalls das letzte Mal, als ich es noch ausprobiert
> hatte) nicht einmal mit Objekten umgehen kann.
>
>> Meine aktuelle 'Lösung' sieht so aus daß ich drei geteilte Variablen
>> $lock_access, $main_changed, $thread_changed zur Synchronisation
>> verwende und die Datenstruktur mit Data::Dumper in eine Datei schreibe.
>> Von der jeweils anderen Seite lese ich den Inhalt wieder aus und per
>> "eval $content" ist er dann verfügbar.
>> Das gefällt mir so nicht sehr, aber da ich die Daten sowieso auf
>> Platte speichern muß habe ich gleich zwei Fliegen mit einer Klappe
>> erschlagen.
>
> Wenn du es einen Tick schneller haben willst, kannst du auch Storable
> verwenden. Für einen Benchmark-Vergleich siehe auch hier:
> http://idisk.mac.com/christian.hansen/Public/perl/serialize. pl
>
> Man könnte die Ausgabe der Serializer auch in einer Perl-Variablen
> speichern und nur diese mit threads::shared teilen...

danke für den Tip. Es beruhigt mich daß es keine viel optimalere
Lösung gibt. Das Ganze per "Storable" zu lösen und den in eine
geteilte Variable zu legen scheint bis jetzt das vielversprechendste
allgemeine Grundmuster für dieses Problem zu sein.

Ich hoffe in Perl6 wird es was Besseres geben.

Ich werde wohl trotzdem erstmal bei meiner bisherigen Lösung bleiben,
da ich die Struktur sowieso speichern muß und da Data::Dumper den
Vorteil der Lesbarkeit hat. In Zeitprobleme bin ich bis jetzt
nicht gekommen, das liegt aber an der Anwendung.


Grüße,
Torsten.