Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Massives Problem im Primsieb
Gehe zu Seite 1, 2  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 81

BeitragVerfasst am: 02.12.2022, 17:23    Titel: Massives Problem im Primsieb Antworten mit Zitat

Hallo Gemeinde !

Ich programmiere diverse Siebe mit Primzahlen, was mit mehreren Threads (2,4 oder mehr) organisiert wird. Alle Thread sieben in einem Feld, was über SHARED definiert wird und durch BIT-Setzung passiert.

Mit mulmigen Gefühl stellte ich erneut fest, dass entweder ein Bit gesetzt wird, obwohl garkeins gesetzt werden sollte (ganz selten), oder es wird keines gesetzt, wenns aber sein sollte.

Ich weiß, das mir einige Grundlagen fehlen bzgl. simulatanes Handling.

Meine Frage ist, wie kann man diese Fehler beheben ?

Ich formuliere es mal knapp.

Generiere Thread1,Thread2,Thread3,Thread4

Siebe in Thread1 mit der i-ten Primzahl, wobei i=1,5,9,13 usw
Siebe in Thread2 mit der i-ten Primzahl, wobei i=2,6,10,14 usw
Siebe in Thread3 mit der i-ten Primzahl, wobei i=3,7,11,15 usw
Siebe in Thread4 mit der i-ten Primzahl, wobei i=4,8,12,16 usw

Alle setzen ein BIT in einem Masterfeld im Hauptteil.

Nach der Auswertung kommen zu <0.1%? Fehler.
Ein 2.ter Testlauf liefert nur zu 99.99% identische Werte.

Was gibt es für Befehle, die ein gleichzeitiges Zugreifen koordinieren ?

Danke im Voraus !
_________________
Umfangreichste Angaben zu Primzahl k-Tupel
https://www.pzktupel.de/ktuplets.php
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4594
Wohnort: ~/

BeitragVerfasst am: 02.12.2022, 20:22    Titel: Antworten mit Zitat

Für Multithreading gibt es MUTEXCREATE / MUTEXLOCK / MUTEXUNLOCK / MUTEXDESTROY sowie CONDCREATE / CONDWAIT / CONDSIGNAL / CONDBROADCAST / CONDDESTROY (hier der Überblick).

Wirklich viel sagen kann ich dazu nicht; mit Mutexen habe ich nur wenig, mit Conditonal Variables überhaupt keine eigene Erfahrung. Ob die Bearbeitung in mehreren Threads aber effektiv ist, hängt davon ab, wie häufig synchronisiert werden muss. Idealerweise sollte der Thread möglichst viel eigenständig arbeiten können, bevor er die Lese-/Schreibzugriffe für andere Threads sperrt, um zu synchronisieren.
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 81

BeitragVerfasst am: 03.12.2022, 07:12    Titel: Antworten mit Zitat

Danke erstmal.

Ich konnte das Problem eindämmen..teils lags am Code selbst, aber sehr minimal entstehen dennoch Verluste (1:1000), damit kann man leben.

Keine Verluste sind, aber eben langsamer, in 4 Arrays zu sieben und diese nach Belegung am Ende abgleichen.
_________________
Umfangreichste Angaben zu Primzahl k-Tupel
https://www.pzktupel.de/ktuplets.php
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 81

BeitragVerfasst am: 05.12.2022, 20:22    Titel: Antworten mit Zitat

Ich muss nochmal reingrätschen.

Also es ist wie es ist, greifen mehrere Threads (bei mir 4 mit 4 echten Kernen) zum Bitsetzen auf eine Feld zu, gibt es Verluste. Nicht alle werden gesetzt. Gibt es eine Lösung für dieses Problem oder ist das einfach unumgänglich ?!

Da die Bitsetzung xfach schneller ist, als die "Einssetzung" im UBYTE-Feld, ziehe ich das vor.

Erledigt das ein Thread gibt es keine Aussetzer.
Danke!
_________________
Umfangreichste Angaben zu Primzahl k-Tupel
https://www.pzktupel.de/ktuplets.php
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4594
Wohnort: ~/

BeitragVerfasst am: 05.12.2022, 21:21    Titel: Antworten mit Zitat

Wenn jeder Thread für sich genommen korrekt funktioniert (davon gehe ich mal aus), kann es zu den Fehlern nur kommen, wenn die Lese- und Schreibzugriffe nicht stimmen. Beispiel: Thread 1 und Thread 2 lesen den Wert der Variablen ein. Thread 1 schreibt einen neuen Wert in die Variable (durch das Setzen eines Bits), Thread 2 schreibt ebenfalls einen neuen Wert und überschreibt damit den zuvor von Thread 1 gesetzten Wert. Auch wenn Lesen und Schreiben in einem einzigen FreeBASIC-Befehl stattfindet, sind das intern in der Regel mehrere Schritte, und da die Threads "zeitgleich" bearbeitet werden, können sich die Anweisungen jederzeit gegenseitig in die Quere kommen.

Als Lösung müsstest du bei jedem Lese- und Schreibzugriff auf eine SHARED-Variable ein MUTEXLOCK durchführen.
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 05.12.2022, 21:27    Titel: Antworten mit Zitat

Tutorial ...
... Mutex: https://www.freebasic-portal.de/tutorials/mutexe-54.html
... Threading: https://www.freebasic-portal.de/tutorials/threading-56.html


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 81

BeitragVerfasst am: 06.12.2022, 06:29    Titel: Antworten mit Zitat

Also ich komm nicht klar mit den MUTEX-Befehlen, was mein Anliegen ist.
Ich gebe mal das Sieb hier aus, nur die 4 Threads...wo muss jetzt was/wo gesetzt werden, damit bei 4 Zugriffen nix verloren geht. Hier zählt eben jede milliardste Sekunde

Das Feld A(...) ist global und über SHARED organisiert und wird mit Bitsetzung 4fach befeuert.
Immerhin wird kein Bit falsch gesetzt, also ungesiebt bleibt ungesiebt.

Das Feld A ist mal hier UINTEGER , damit 64 Bits gesetzt werden können, üblich sind aber UBYTE.

Somit im Vergleich A(800000) AS UBYTE = A(100000) AS UINTEGER

Code:

REM THREAD 1 ****************

Sub MyThread1 (ByVal Parameter as Any Ptr)
DIM AS ULONG MAS,P,U,q1,ga,gb,AD

ga=1:gb=1:P=0
WHILE P<maxs
P+=PZ1(ga):MAS=MA(gb)
U=P-((TS-MAS*O) MOD P)
q1=(U+(MAS SHL 1)) MOD P
IF q1<U THEN SWAP q1,U
AD=0
WHILE AD+P<50000300
A(( U+AD) SHR 6)=BITSET(A(( U+AD) SHR 6),( U+AD) MOD 64)
A((q1+AD) SHR 6)=BITSET(A((q1+AD) SHR 6),(q1+AD) MOD 64)
AD+=P
WEND
IF ( U+AD)<50000300 THEN A(( U+AD) SHR 6)=BITSET(A(( U+AD) SHR 6),( U+AD) MOD 64)
IF (q1+AD)<50000300 THEN A((q1+AD) SHR 6)=BITSET(A((q1+AD) SHR 6),(q1+AD) MOD 64)
ga+=1:gb+=4
WEND

END sub

REM TH2 **********************************

Sub MyThread2 (ByVal Parameter as Any Ptr)
DIM AS ULONG MAS,P,U,q1,ga,gb,AD

ga=1:gb=2:P=0
WHILE P<maxs
P+=PZ2(ga):MAS=MA(gb)
U=P-((TS-MAS*O) MOD P)
q1=(U+(MAS SHL 1)) MOD P
IF q1<U THEN SWAP q1,U
AD=0
WHILE AD+P<50000300
A(( U+AD) SHR 6)=BITSET(A(( U+AD) SHR 6),( U+AD) MOD 64)
A((q1+AD) SHR 6)=BITSET(A((q1+AD) SHR 6),(q1+AD) MOD 64)
AD+=P
WEND
IF ( U+AD)<50000300 THEN A(( U+AD) SHR 6)=BITSET(A(( U+AD) SHR 6),( U+AD) MOD 64)
IF (q1+AD)<50000300 THEN A((q1+AD) SHR 6)=BITSET(A((q1+AD) SHR 6),(q1+AD) MOD 64)
ga+=1:gb+=4
WEND

END sub

Sub MyThread3 (ByVal Parameter as Any Ptr)
DIM AS ULONG MAS,P,U,q1,ga,gb,AD
ga=1:gb=3:P=0
WHILE P<maxs
P+=PZ3(ga):MAS=MA(gb)
U=P-((TS-MAS*O) MOD P)
q1=(U+(MAS SHL 1)) MOD P
IF q1<U THEN SWAP q1,U
AD=0
WHILE AD+P<50000300
A(( U+AD) SHR 6)=BITSET(A(( U+AD) SHR 6),( U+AD) MOD 64)
A((q1+AD) SHR 6)=BITSET(A((q1+AD) SHR 6),(q1+AD) MOD 64)
AD+=P
WEND
IF ( U+AD)<50000300 THEN A(( U+AD) SHR 6)=BITSET(A(( U+AD) SHR 6),( U+AD) MOD 64)
IF (q1+AD)<50000300 THEN A((q1+AD) SHR 6)=BITSET(A((q1+AD) SHR 6),(q1+AD) MOD 64)
ga+=1:gb+=4
WEND

END sub

Sub MyThread4 (ByVal Parameter as Any Ptr)
DIM AS ULONG MAS,P,U,q1,ga,gb,AD
ga=1:gb=4:P=0

WHILE P<maxs
P+=PZ4(ga):MAS=MA(gb)
U=P-((TS-MAS*O) MOD P)
q1=(U+(MAS SHL 1)) MOD P
IF q1<U THEN SWAP q1,U
AD=0
WHILE AD+P<50000300
A(( U+AD) SHR 6)=BITSET(A(( U+AD) SHR 6),( U+AD) MOD 64)
A((q1+AD) SHR 6)=BITSET(A((q1+AD) SHR 6),(q1+AD) MOD 64)
AD+=P
WEND
IF ( U+AD)<50000300 THEN A(( U+AD) SHR 6)=BITSET(A(( U+AD) SHR 6),( U+AD) MOD 64)
IF (q1+AD)<50000300 THEN A((q1+AD) SHR 6)=BITSET(A((q1+AD) SHR 6),(q1+AD) MOD 64)
ga+=1:gb+=4
WEND

END sub

_________________
Umfangreichste Angaben zu Primzahl k-Tupel
https://www.pzktupel.de/ktuplets.php


Zuletzt bearbeitet von pzktupel am 06.12.2022, 14:53, insgesamt 2-mal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 06.12.2022, 13:24    Titel: Antworten mit Zitat

Hi,

der Code ist leider etwas unübersichtlich ... aber, wenn "A" eine Shared Variable ist, dann "um" A herum.

Code:

Sub MyThread4 (ByVal Parameter as Any Ptr)
'...
WHILE AD+P<50000300
mutexlock(...)
A(( U+AD) SHR 6)=BITSET(A(( U+AD) SHR 6),( U+AD) MOD 64)
A((q1+AD) SHR 6)=BITSET(A((q1+AD) SHR 6),(q1+AD) MOD 64)
mutexunlock(...)
'...WEND
mutexlock(...)
IF ( U+AD)<50000300 THEN A(( U+AD) SHR 6)=BITSET(A(( U+AD) SHR 6),( U+AD) MOD 64)
IF (q1+AD)<50000300 THEN A((q1+AD) SHR 6)=BITSET(A((q1+AD) SHR 6),(q1+AD) MOD 64)
mutexunlock(...)
WEND
'...
END sub


zur optimierung kannst auch noch
Code:

'...
IF ( U+AD)<50000300 THEN
    mutexlock(...)
    A(( U+AD) SHR 6)=BITSET(A(( U+AD) SHR 6),( U+AD) MOD 64)
    mutexunlock(...)
End If
'...


durchühren. Das beschränkt das mutexlock/unlock auf den wirklich zugriff auf die variable

und, mutexcreate / destroy nicht vergessen.

PS: Die beiden tutorials helfen dir hier. Dort ist alles gut erklärt


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 81

BeitragVerfasst am: 06.12.2022, 14:46    Titel: Antworten mit Zitat

Puh...
Also ich kann mir eher ein Bild machen, wenn das Gewollte fehlerfrei läuft. Oftmals kann ich mir kein Bild machen, was für andere selbstverständlich ist...wenn es mir neu ist. Dieses mutexlock(...) sagt mir jetzt garnix, was in die Klammer soll, deshalb hier das komplette Sieb. Ich lese das 100mal in den Hinweisen, aber es unklar...
Unwichtige Zeilen entfernt...diente zur synchronisation zum 2. PC
Es ist ein komplexes inhaltliches Sieb, deshalb brauch ich an den wichtigen Punkten in den Threads genau den Teil, damit keine Bitsetzung futsch geht.
Denke, das ist schon anspruchsvoll...wenn zu lange Wartezeiten entstehen, bringt das ja dann auch nix mehr...da kann man auch ein Thread und viele gleiche Instanzen laufen lassen. Der ganze Teil mit dem PseudoPrimTest, würde entfallen, wenn keine Bitsetzung verloren gehen würde...so dient es der Fehlerkorrektur.

Code:

#INCLUDE "windows.bi"
#INCLUDE "vbcompat.bi"
#include "Big-Int overload.bi"
 
Dim As Any Ptr T1,T2,T3,T4,WR
DIM AS UINTEGER PPP,PP,U,AD
DIM SHARED AS UINTEGER maxs,TS,maxg,TSS
DIM SHARED AS ULONG dis,TNR,L,x,y,k,f1,f2,f3,f4,PP1,PP2,PP3,PP4,N2
DIM SHARED AS USHORT RG,RH,O,ocstart,i,leer
DIM SHARED AS STRING OS,SYN,T,S,TKN
REDIM SHARED OFS(14) AS UBYTE
REDIM SHARED A(6300000) AS UBYTE
REDIM SHARED  ANZ(50005000) AS USHORT
REDIM SHARED ANZC(50005000) AS USHORT
DIM SHARED AS BIGINT  Px1,Px2,Px3,Px4

Function bigint_miller_test_2(Byref a As bigint, Byref _base As bigint) As Long
   'Checks the Miller primality test for number [a] with base [_base].
   'is_prime = 0: [a] is composite
   'is_prime = 1: [a] is a "strong PROBABLY prime" (Not 100% prime, only 75% by Rabin's theoreme)
   Dim As Long is_prime
   Select Case big_int_miller_test(a.numptr, _base.numptr, @is_prime)
   Case 0
      Return is_prime
   Case 1
      Print "[base] is too small. It must be 1 < base < (a - 1)"
   Case 2
      Print "[base] is too high. It must be 1 < base < (a - 1)"
   Case Else
      Print "internal error"
   End Select
End Function





REM *************

 KILL "Z:\TUPEL\c01":KILL "Z:\TUPEL\c02":KILL "Z:\TUPEL\c03":KILL "Z:\TUPEL\c04"

OFS(0)=11:OFS(1)=17:OFS(2)=29:OFS(3)=41:OFS(4)=59:
OFS(5)=71:OFS(6)=101:OFS(7)=107:OFS(8)=137:OFS(9)=149:
OFS(10)=167:OFS(11)=179:OFS(12)=191:OFS(13)=197:OFS(14)=209:


REM *************

REDIM SHARED MA(17500000) AS ULONG
REDIM SHARED PZ1(4300000) AS USHORT
REDIM SHARED PZ2(4300000) AS USHORT
REDIM SHARED PZ3(4300000) AS USHORT
REDIM SHARED PZ4(4300000) AS USHORT


OPEN "E:\PRIMGEN\primes.src" FOR INPUT AS #18
T=INPUT(9,#18):T=INPUT(51300000,#18)
CLOSE #18

PRINT "*"

PPP=7:PP=1
WHILE PP<51299999
dis=VALUINT(MID(T,PP,3)):PPP+=dis:f1+=1:PZ1(f1)=PPP-PP1:PP1=PPP:PP+=3
dis=VALUINT(MID(T,PP,3)):PPP+=dis:f2+=1:PZ2(f2)=PPP-PP2:PP2=PPP:PP+=3
dis=VALUINT(MID(T,PP,3)):PPP+=dis:f3+=1:PZ3(f3)=PPP-PP3:PP3=PPP:PP+=3
dis=VALUINT(MID(T,PP,3)):PPP+=dis:f4+=1:PZ4(f4)=PPP-PP4:PP4=PPP:PP+=3
WEND
PRINT "x"
OPEN "tnr" FOR INPUT AS #20:INPUT #20,TNR:CLOSE #20

T=""
IF NOT FILEEXISTS("E:\TUPEL\provePC1.txt") THEN TNR=TNR+2
TKN=RIGHT("0"+STR(TNR),2)

IF TNR<3 THEN SYN="Z:\TUPEL\c"+TKN:OPEN "Z:\TUPEL\parameter21.txt" FOR INPUT AS #1
IF TNR>2 THEN SYN="E:\TUPEL\c"+TKN:OPEN "E:\TUPEL\parameter21.txt" FOR INPUT AS #1
INPUT #1,TS:CLOSE #1
TS=(TS\50000000)*50000000

TS=TS+50000000*(TNR-1)
 

REDIM SHARED GO(50000) AS UBYTE

IF TNR<3 THEN SYN="Z:\TUPEL\c"+TKN:OPEN "Z:\TUPEL\_GAP02\_gap2open.txt" FOR INPUT AS #3
IF TNR>2 THEN SYN="E:\TUPEL\c"+TKN:OPEN "E:\TUPEL\_GAP02\_gap2open.txt" FOR INPUT AS #3

WHILE NOT EOF(3)
INPUT #3,i:GO(i)=1
WEND
CLOSE #3
 


maxs=INT(((TS+50000300)*210)^0.5)
leer=0


REM THREAD 1 ****************

Sub MyThread1 (ByVal Parameter as Any Ptr)
DIM AS ULONG MAS,P,U,q1,ga,gb,AD

ga=1:gb=1:P=0
WHILE P<maxs
P+=PZ1(ga):MAS=MA(gb)
U=P-((TS-MAS*O) MOD P)
q1=(U+(MAS SHL 1)) MOD P
IF q1<U THEN SWAP q1,U
AD=0
WHILE AD+P<50000300
A(( U+AD) SHR 3)=BITSET(A(( U+AD) SHR 3),( U+AD) MOD 8)
A((q1+AD) SHR 3)=BITSET(A((q1+AD) SHR 3),(q1+AD) MOD 8)
AD+=P
WEND
IF ( U+AD)<50000300 THEN A(( U+AD) SHR 3)=BITSET(A(( U+AD) SHR 3),( U+AD) MOD 8)
IF (q1+AD)<50000300 THEN A((q1+AD) SHR 3)=BITSET(A((q1+AD) SHR 3),(q1+AD) MOD 8)
ga+=1:gb+=4
WEND

END sub

REM TH2 **********************************

Sub MyThread2 (ByVal Parameter as Any Ptr)
DIM AS ULONG MAS,P,U,q1,ga,gb,AD

ga=1:gb=2:P=0
WHILE P<maxs
P+=PZ2(ga):MAS=MA(gb)
U=P-((TS-MAS*O) MOD P)
q1=(U+(MAS SHL 1)) MOD P
IF q1<U THEN SWAP q1,U
AD=0
WHILE AD+P<50000300
A(( U+AD) SHR 3)=BITSET(A(( U+AD) SHR 3),( U+AD) MOD 8)
A((q1+AD) SHR 3)=BITSET(A((q1+AD) SHR 3),(q1+AD) MOD 8)
AD+=P
WEND
IF ( U+AD)<50000300 THEN A(( U+AD) SHR 3)=BITSET(A(( U+AD) SHR 3),( U+AD) MOD 8)
IF (q1+AD)<50000300 THEN A((q1+AD) SHR 3)=BITSET(A((q1+AD) SHR 3),(q1+AD) MOD 8)
ga+=1:gb+=4
WEND

END sub

Sub MyThread3 (ByVal Parameter as Any Ptr)
DIM AS ULONG MAS,P,U,q1,ga,gb,AD
ga=1:gb=3:P=0
WHILE P<maxs
P+=PZ3(ga):MAS=MA(gb)
U=P-((TS-MAS*O) MOD P)
q1=(U+(MAS SHL 1)) MOD P
IF q1<U THEN SWAP q1,U
AD=0
WHILE AD+P<50000300
A(( U+AD) SHR 3)=BITSET(A(( U+AD) SHR 3),( U+AD) MOD 8)
A((q1+AD) SHR 3)=BITSET(A((q1+AD) SHR 3),(q1+AD) MOD 8)
AD+=P
WEND
IF ( U+AD)<50000300 THEN A(( U+AD) SHR 3)=BITSET(A(( U+AD) SHR 3),( U+AD) MOD 8)
IF (q1+AD)<50000300 THEN A((q1+AD) SHR 3)=BITSET(A((q1+AD) SHR 3),(q1+AD) MOD 8)
ga+=1:gb+=4
WEND

END sub

Sub MyThread4 (ByVal Parameter as Any Ptr)
DIM AS ULONG MAS,P,U,q1,ga,gb,AD
ga=1:gb=4:P=0

WHILE P<maxs
P+=PZ4(ga):MAS=MA(gb)
U=P-((TS-MAS*O) MOD P)
q1=(U+(MAS SHL 1)) MOD P
IF q1<U THEN SWAP q1,U
AD=0
WHILE AD+P<50000300
A(( U+AD) SHR 3)=BITSET(A(( U+AD) SHR 3),( U+AD) MOD 8)
A((q1+AD) SHR 3)=BITSET(A((q1+AD) SHR 3),(q1+AD) MOD 8)
AD+=P
WEND
IF ( U+AD)<50000300 THEN A(( U+AD) SHR 3)=BITSET(A(( U+AD) SHR 3),( U+AD) MOD 8)
IF (q1+AD)<50000300 THEN A((q1+AD) SHR 3)=BITSET(A((q1+AD) SHR 3),(q1+AD) MOD 8)
ga+=1:gb+=4
WEND

END sub



Sub MyThread9 (ByVal Parameter as Any Ptr)
DIM AS UINTEGER U,i,k,AD,N1,N2,G1,G2

      IF TNR<3 THEN OPEN "Z:\TUPEL\_GAP02\GAP21log."+TKN FOR APPEND AS #8
      IF TNR>2 THEN OPEN "E:\TUPEL\_GAP02\GAP21log."+TKN FOR APPEND AS #8

      IF TNR<3 THEN  OPEN "Z:\TUPEL\_GAP02\GAP21log.24p" FOR APPEND AS #9
      IF TNR>2 THEN  OPEN "E:\TUPEL\_GAP02\GAP21log.24p" FOR APPEND AS #9

      IF TNR<3 THEN  OPEN "Z:\TUPEL\_GAP02\GAP21log.bug" FOR APPEND AS #10
      IF TNR>2 THEN  OPEN "E:\TUPEL\_GAP02\GAP21log.bug" FOR APPEND AS #10

N1=OFS(0)

FOR U=0 TO 50000299
   FOR   i=0 TO 14
   IF BIT(ANZC(U),i)=0 THEN GOTO NI ELSE N2=U*210+OFS(i)
   AD=N2-N1:N1=N2
   
   IF AD<10000 THEN GOTO NI
   G1=TSS+N2-AD:Px1=STR(G1):Px2=STR(G1+2)
   G2=G1+AD:Px3=STR(G2):Px4=STR(G2+2)
   IF bigint_miller_test_2(px1,2)=0 THEN   PRINT #10,G1,AD,"-6":GOTO NI
   IF bigint_miller_test_2(px2,2)=0 THEN PRINT #10,G1,AD,"-6":GOTO NI
   IF bigint_miller_test_2(px3,2)=0 THEN   PRINT #10,G1,AD,"+6":GOTO NI
   IF bigint_miller_test_2(px4,2)=0 THEN PRINT #10,G1,AD,"+6":GOTO NI
      
   IF AD>24000 THEN PRINT #9,"  ";AD;" ";G1;" ";TIME;" ";TKN

      IF GO(AD\6)=1 THEN BEEP_ 5000,2000:PRINT #8,"  ";AD\6;" ";G1
      IF AD<maxg THEN GOTO NI
      
      IF TNR<3 THEN OPEN "Z:\TUPEL\_GAP02\GAP21.txt" FOR APPEND AS #66:PRINT #66,AD,N2-AD,N2:CLOSE #66
      IF TNR>2 THEN OPEN "E:\TUPEL\_GAP02\GAP21.txt" FOR APPEND AS #66:PRINT #66,AD,N2-AD,N2:CLOSE #66
   
   NI:
   
   NEXT i
NEXT U


leer=0:
CLOSE #8
CLOSE #9
CLOSE #10
END sub



REM HAUPTEIL ++++++++++++++++++++++++++++++++++++++++++++++++

OPEN "E:\TUPEL\07#_320M.src" FOR Binary Access Read AS #111
T=INPUT(153900000,#111)
CLOSE #111

x=0
y=1
WHILE y<153900000
x+=1:MA(x)=VALULNG(MID(T,y,9))
y+=9
WEND
T=""

ABHIER:
FOR ocstart=0 TO 14
O=OFS(ocstart)

T1 = ThreadCreate(@MyThread1)
T2 = ThreadCreate(@MyThread2)
T3 = ThreadCreate(@MyThread3)
T4 = ThreadCreate(@MyThread4)

ThreadWait T1
ThreadWait T2
ThreadWait T3
ThreadWait T4

FOR U=0 TO 6250030
IF (A(U) AND (1 SHL 0))=0 THEN ANZ(U*8+0)=ANZ(U*8+0)+(1 SHL ocstart)
IF (A(U) AND (1 SHL 1))=0 THEN ANZ(U*8+1)=ANZ(U*8+1)+(1 SHL ocstart)
IF (A(U) AND (1 SHL 2))=0 THEN ANZ(U*8+2)=ANZ(U*8+2)+(1 SHL ocstart)
IF (A(U) AND (1 SHL 3))=0 THEN ANZ(U*8+3)=ANZ(U*8+3)+(1 SHL ocstart)
IF (A(U) AND (1 SHL 4))=0 THEN ANZ(U*8+4)=ANZ(U*8+4)+(1 SHL ocstart)
IF (A(U) AND (1 SHL 5))=0 THEN ANZ(U*8+5)=ANZ(U*8+5)+(1 SHL ocstart)
IF (A(U) AND (1 SHL 6))=0 THEN ANZ(U*8+6)=ANZ(U*8+6)+(1 SHL ocstart)
IF (A(U) AND (1 SHL 7))=0 THEN ANZ(U*8+7)=ANZ(U*8+7)+(1 SHL ocstart)

NEXT U
   REDIM A(6350000) AS UBYTE   
NEXT ocstart

S: IF leer=0 THEN GOTO WEITER ELSE SLEEP 5000:GOTO S
WEITER:
TSS=TS*210

FOR U=0 TO 50000299
ANZC(U)=ANZ(U)
NEXT U
 
leer=1

WR = ThreadCreate(@MyThread9)
 
REDIM ANZ(50005000) AS USHORT

TS=TS+200000000

GOTO ABHIER

_________________
Umfangreichste Angaben zu Primzahl k-Tupel
https://www.pzktupel.de/ktuplets.php
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 06.12.2022, 15:10    Titel: Antworten mit Zitat

pzktupel hat Folgendes geschrieben:
... Dieses mutexlock(...) sagt mir jetzt garnix, was in die Klammer soll, ...


lesen:
... Mutex: https://www.freebasic-portal.de/tutorials/mutexe-54.html
... Threading: https://www.freebasic-portal.de/tutorials/threading-56.html


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4594
Wohnort: ~/

BeitragVerfasst am: 06.12.2022, 19:37    Titel: Antworten mit Zitat

Kurz gesagt: du brauchst zunächst einmal ein Mutex, das du über MUTEXCREATE erzeugst, z. B.
Code:
DIM SHARED AS ANY PTR meinMutex = MUTEXCREATE

Wenn du in einem der Threads ein MUTEXLOCK(meinMutex) ausführst, sichert sich dieser Thread gewissermaßen exklusive Ausführrechte. Wenn nun ein anderer Thread ebenfalls ein MUTEXLOCK(meinMutex) durchführen will, muss er zunächst warten, bis der erste Thread den gesperrten Mutex über MUTEXUNLOCK(meinMutex) wieder frei gegeben hat.

Aber auch ich würde dir das Tutorial von ThePuppetMaster sehr ans Herz legen; da sind auch einige Fallstricke aufgeführt, die man beachten muss.
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 81

BeitragVerfasst am: 06.12.2022, 21:46    Titel: Antworten mit Zitat

Ich habe Ansatzweise mal sowas eingebunden, aber das wurde total langsam...daher unbrauchbar.

Ein anderer mathematischer Trick war mir eingefallen, was die Fehlerquote ohne MUTEX auf Null setzte....war auch langsamer, daher unbrauchbar.

Ich bin wieder zum alten im Moment zurück und bügel die Fehler mit einem Zusatzprogramm aus.

Der Trick war, splitte das Intervall in 4 Teile und siebe versetzt ein Teilintervall durch , rücke dann eines weiter...zu deutsch:
[in Mio]
STEP 1
Thread 1 siebt 0-12,5
Thread 2 siebt 12,5-25
Thread 3 siebt 25-37,5
Thread 4 siebt 37,5-50
STEP 2
Thread 1 siebt 12,5-25
Thread 2 siebt 25-37,5
Thread 3 siebt 37,5-50
Thread 4 siebt 0-12,5
STEP 3
Thread 1 siebt 25-37,5
Thread 2 siebt 37,5-50
Thread 3 siebt 0-12,5
Thread 4 siebt 12,5-25
STEP4
Thread 1 siebt 37,5-50
Thread 2 siebt 0-12,5
Thread 3 siebt 12,5-25
Thread 4 siebt 25-37,5

Ist aber eben auch wieder langsamer, leider.
Das Programm ist mit der Aufgabe auf 2 PCs rund 5 Wochen beschäftigt...da zählt jede Verbesserung.

Konkret , die Primzahlzwillinge auf Rekordlücken bis 10^17 anzuheben....
https://pzktupel.de/RecordGaps/GAP02.php
_________________
Umfangreichste Angaben zu Primzahl k-Tupel
https://www.pzktupel.de/ktuplets.php
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 06.12.2022, 23:19    Titel: Antworten mit Zitat

Also, ich habe mir jetzt mal deinen Sourcecode angesehen und muss dir leider ein paar Punkte nennen.
Ist keinesfalls böse gemeint, also, bitte nicht falsch verstehen.

1. Bitte arbeite mit mehr abstand ... Deine Quellcodezeilen sind fast ohne SPACE. Das macht es EXTREM schwer ihn zu lesen und die übersicht zu behalten.
Code:

IF (q1+AD)<50000300 THEN A((q1+AD) SHR 3)=BITSET(A((q1+AD) SHR 3),(q1+AD) MOD 8)
IF (q1 + AD) < 50000300 THEN A((q1 + AD) SHR 3) = BITSET(A((q1 + AD) SHR 3), (q1 + AD) MOD 8)

Gerne auch mit TAB arbeiten, das machts auch viel übersichtlicher

2. bitte .. bitte BITTE gewöhne dir an die Variablen nicht nur mit einem oder 2 Buchstaben zu betiteln, sondern auch etwas Aussagekräftiger. Ein A für irgend ein Array, das irgend wo im code mal irgend wo deklariert wurde ist ÜBELST schwer zu finden. Wenn ich in meiner IDE nach einem A suche, dann suche ich mich zu tode. Gerne also etwas in der art "BitArray" oder etwas, das den Zweck der Variable verdeutlicht.

3. Dann noch eine kleine Anmerkung. Du hast 2 Haupt-Code teile in deinem Quellcode .. Einmal irgend wo am anfang, dann die Thread-Sub's und dann nochmal einen hauptteil. Bitte diese teile an einer stelle. Sonst passiert es schnell, das man inmitten von sub routinen irgend welche dinge tut, die im hauptprogramm ausgeführt werden, man aber beim debuggen irgend wie nicht findet. Macht quasi einen "unorganisierten" eindruck.

Aber genug zu dem und jetzt zu deinem Theading Problem.

Wenn ich das richtig gesehen habe, dann hast du 4 Thread-Sub's, die faktisch alle identisch sind, bis auf 2 Punkte. Einmal das PZ Array (1, 2, 3, 4) und einmal die GB Variable in der Thread-Sub, die auch entsprechend 1, 2, 3 und 4 beinhaltet.

Am besten gestaltest du eine Thread Routine so (gerade, wenn es um massive Parallelität geht) das du die Sub's nicht jedes mal neu schraiben musst, sondern eine generelle Sub hast, welche du mit wenigen Parametern "Initialisieren" kannst. Das hat den Vorteil, das du nur eine Sub Routine Optimieren musst, und sie z.B. per Schleife einfach 100x oder 1000x aufrufen kannst.

Aber zurück zum Thread Sub ...

Du hast also 4 PZ Arrays, welche sich nach dem programmstart nicht mehr ändern werden. Du greifst (wenn ich das richtig gesehen habe) nur am anfang darauf zu, schreibst werte rein, und nutzt sie dann nur noch zum auslesen. Du kannst sie also hervorragend parallel ohne mutex nutzen (auch ohne mutex).

Ich empfehle dir ein Mehrdimensionales Array. Das hat den vorteil, das du nur noch eine "index-nummer" angeben musst, um das passende array zu selectieren.
Code:

REDIM SHARED PZ(1 to 4, 0 to 4300000) AS USHORT


Damit kannst du dann im Thread via ...
Code:

'...
   P += PZ(INDEX, ga): MAS = MA(gb)
'...

zugreifen.

Vorteil: Du hast in der Thread-Sub eine gb Variable. Sie ist gleich mit der Thread-Nummer und damit auch mit dem Index der PZ. Die Folge ...
Code:

'...
   P += PZ(gb, ga): MAS = MA(gb)
'...


Und damit hast du aus 2 Thread-Sub Routinen nur noch eine gemacht.

Code:

Sub MyThread (ByVal Parameter as Any Ptr)
DIM AS ULONG MAS, P, U, q1, ga, gb, AD
ga = 1: gb = 1: P = 0
WHILE P < maxs
   P += PZ(gb, ga): MAS = MA(gb)
   U = P - ((TS - MAS * O) MOD P)
   q1 = (U + (MAS SHL 1)) MOD P
   IF q1 < U THEN SWAP q1, U
   AD = 0
   WHILE (AD + P) < 50000300
      A(( U + AD) SHR 3) = BITSET(A(( U + AD) SHR 3), ( U + AD) MOD 8)
      A((q1 + AD) SHR 3) = BITSET(A((q1 + AD) SHR 3), (q1 + AD) MOD 8)
      AD += P
   WEND
   IF ( U + AD) < 50000300 THEN A(( U + AD) SHR 3) = BITSET(A(( U + AD) SHR 3), ( U + AD) MOD 8)
   IF (q1 + AD) < 50000300 THEN A((q1 + AD) SHR 3) = BITSET(A((q1 + AD) SHR 3), (q1 + AD) MOD 8)
   ga += 1: gb += 4
WEND
End Sub


Jetzt nur noch beim aufruf dieses Threads ein index an die Sub übergeben, damit das auch funktioniert
Code:

T1 = ThreadCreate(@MyThread, 1)
T2 = ThreadCreate(@MyThread, 2)
T3 = ThreadCreate(@MyThread, 3)
T4 = ThreadCreate(@MyThread, 4)


... und diese Indexnummer im Parameter in der Thread-Sub verwenden ...
Code:

Sub MyThread (ByVal Parameter as Any Ptr)
DIM AS ULONG MAS, P, U, q1, ga, gb, AD
ga = 1: gb = cast(ULong, Parameter): P = 0
WHILE P < maxs
'...


Und schon könntest du theoretisch ...
Code:

Dim TThreadMax as UInteger = 100
Dim TThreadID(TThreadMax) as Any Ptr
For X as Integer = 1 to 100
   TThreadID(X) = ThreadCreate(@MyThread, X)
Next

beliebig viele Threads starten.

ACHTUNG! Bitte dann auch nicht vergessen das PZ Array entsprechend zu inizialisieren.

z.B. mit
Code:

'...
Dim TThreadMax as UInteger = 100
REDIM SHARED PZ(1 to TThreadMax, 0 to 4300000) AS USHORT
'...


Und jetzt zur Optimierung deines eigentlichen Thread-Codes.

Wenn ich mir ansehe, wie das verhalten des Codes ist, sprich .. was tut es, wie lange tut es das, wann tut es das, wann muss es etwas tun, usw. dann kann man gut erkennen, das der Thread (ich nenne das jetzt der einfachheitshalber mal "Filter") .. einfach nur Berechnungen ausführt, und das ganze mit einer bestimmten abhängigkeit in ein Array packt.
Zudem fällt mir auf, das der Zugriff auf dieses Array (A) im Filter NUR schreibend erfolgt. Du Prüfst nicht, ob ein Bit gesetzt wurde, oder nicht, und machst das zu einer abhängigkeit für das weitere Vorgehen.

Dieser Umstand ist in deinem Fall sogar SEHR von Vorteil. Wenn du aus dem Array nichts ausliest, dann beeinflusst das auch keinen anderen Thread. Daher -> Kein Mutex Nötig ... WENN: Man mehrere Arrays für jeden Thread Seperat nutzt.

Daher lieber noch ein multi-Array draus machen...
Code:

'...
Dim TThreadMax as UInteger = 100
REDIM SHARED PZ(1 to TThreadMax, 0 to 4300000) AS USHORT
REDIM SHARED A(0 to TThreadMax, 0 to 6300000) AS USHORT '0 bis xxx WEIL wir später in das index 0 das ergebniss alle xxx rein schreiben und uns damit ein weiteres DIM bla sparen
'...


... und den Thread entsprechend ändern ...
Code:

'...
   WHILE (AD + P) < 50000300
      A(gb, ( U + AD) SHR 3) = BITSET(A(gb, ( U + AD) SHR 3), ( U + AD) MOD 8)
      A(gb, (q1 + AD) SHR 3) = BITSET(A(gb, (q1 + AD) SHR 3), (q1 + AD) MOD 8)
      AD += P
   WEND
   IF ( U + AD) < 50000300 THEN A(gb, ( U + AD) SHR 3) = BITSET(A(gb, ( U + AD) SHR 3), ( U + AD) MOD 8)
   IF (q1 + AD) < 50000300 THEN A(gb, (q1 + AD) SHR 3) = BITSET(A(gb, (q1 + AD) SHR 3), (q1 + AD) MOD 8)
   ga += 1: gb += 4
WEND
End Sub


Dann kannst du nach dem ende der Threads einfach mit ...
Code:

Y as UInteger
For X as Integer = 1 to TThreadMax
   For Y = 1 to 6300000
      A(0, Y) AND= A(X, Y)
   Next
Next

PS: Das "Zusammenführen der Variablen könnte man stat AND auch hervorragend mit Grafischen Maskenoperationen von der Grafikkarte aus erledigen lassen (welche viel flotter bei dieser BIT-Zusammenführung ist)

Anschliessend kannst du dann deine Final-Prüfungen durchführen (Immer mit INDEX:0 auf das A Array) ...
Code:

FOR U=0 TO 6250030
   IF (A(0, U) AND (1 SHL 0))=0 THEN ANZ(U*8+0)=ANZ(U*8+0)+(1 SHL ocstart)
   '...



Es gibt sicher noch so einige Optimierungsmöglichkeiten, aber ist schon spät, und ich muss morgen wieder raus zwinkern

EDIT: mir ist gerade noch aufgefallen, das du in der schleife ein gb += 4 machst.
Also am besten nach dem Init von gb noch ein dim TheadIndex as ulong = gb machen, und das TheadIndex als INDEX für A verwenden.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 81

BeitragVerfasst am: 07.12.2022, 07:11    Titel: Antworten mit Zitat

Danke erstmal für Deine Zeit für mich,
es ist viel nachzulesen um es zu verstehen.

Mit den Mehrdimensionen arbeite ich auch manchmal...aber es gibt oft Laufzeitunterschiede. Nehme aus Prinzip immer die schnellste , weil diese Programme dann richtig Wochen durchziehen.

LG

Nachtrag: Ich habe es weitesgehend eingebunden und auch in etwa verstanden. Leider lässt es sich so nicht kompilieren.

Code:

Sub MyThread (ByVal ID as Any Ptr)
DIM AS ULONG MAS,P,U,q1,ga,gb,AD

PRINT ID
gb = cast(ULong, ID)
ga=1:P=0:AD=0

WHILE P<maxs
P+=PZ(gb,ga):MAS=MA(gb):U=P-((TS-MAS*O) MOD P)
q1=(U+(MAS SHL 1)) MOD P
   WHILE (AD + P) < 50000300
      A(gb, ( U + AD) SHR 3) = BITSET(A(gb, ( U + AD) SHR 3), ( U + AD) MOD 8)
      A(gb, (q1 + AD) SHR 3) = BITSET(A(gb, (q1 + AD) SHR 3), (q1 + AD) MOD 8)
      AD += P
   WEND
   IF ( U + AD) < 50000300 THEN A(gb, ( U + AD) SHR 3) = BITSET(A(gb, ( U + AD) SHR 3), ( U + AD) MOD 8)
   IF (q1 + AD) < 50000300 THEN A(gb, (q1 + AD) SHR 3) = BITSET(A(gb, (q1 + AD) SHR 3), (q1 + AD) MOD 8)
   ga += 1
WEND

END sub
....

Dim T_ID(4) as Any Ptr

T_ID(1) = ThreadCreate(@MyThread,1) REM ZEILE 210
T_ID(2) = ThreadCreate(@MyThread,2) REM ZEILE 211
T_ID(3) = ThreadCreate(@MyThread,3) REM ZEILE 212
T_ID(4) = ThreadCreate(@MyThread,4) REM ZEILE 213

ThreadWait T_ID(1)
ThreadWait T_ID(2)
ThreadWait T_ID(3)
ThreadWait T_ID(4)


Wie ich das deute, 4 mal wird die SUB aufgerufen , wobei
ein Parameter 1 bis 4 übergeben wird, sodas mit dem das A-Feld und PZ-Feld gesondert geschrieben / gelesen wird.

ID soll die Übergabe sein und über gb = cast(ULong, ID) auf gb übertragen werden.

Im Moment beim kompileren kommt:
2GAP1mu_tpm.bas(101) error 20: Type mismatch, before ')' in 'gb = cast(ULong, ID)'
2GAP1mu_tpm.bas(210) warning 1(1): Passing scalar as pointer, at parameter 2 of THREADCREATE()
2GAP1mu_tpm.bas(211) warning 1(1): Passing scalar as pointer, at parameter 2 of THREADCREATE()
...
_________________
Umfangreichste Angaben zu Primzahl k-Tupel
https://www.pzktupel.de/ktuplets.php
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 81

BeitragVerfasst am: 07.12.2022, 15:04    Titel: Antworten mit Zitat

Fazit:
Ich habe das Programm zum laufen bekommen und auch wieder mehrere Varianten der Organisation durchgespielt. Wieder etwas dazu gelernt.
Offen bleibt, wie ich einen Indexwert sauber übergebe
Zur Not hatte ich:
Code:

Dim T_ID(3) as Any Ptr
SLEEP 100:id=0:T_ID(0) = ThreadCreate(@MyThread)
SLEEP 100:id=1:T_ID(1) = ThreadCreate(@MyThread)
SLEEP 100:id=2:T_ID(2) = ThreadCreate(@MyThread)
SLEEP 100:id=3:T_ID(3) = ThreadCreate(@MyThread)

vereinbart, wobei eben gd in der SUB den id-Wert übernimmt.

Leider musste ich wieder feststellen, das alles am Ende halb so fix ist, obwohl der Code sehr übersichtlich nun wirkt. Mit A(gb,(U SHR 3), U MOD cool ...
hat man ja ein 4faches Array, was zum Auslesen wieder am Ende auch Zeit kostet, klar, die Bitsetzung überschneidet sich nicht.

Es läuft wieder das alte Programm, wobei es sehr wenige Fehler durch Bitsetzung gibt.
Zur Fehlerbehebung sei gesagt:
Da jedenfalls kein BIT falsch gesetzt wird ( nur Ausfälle ) , kann man am Ende das Intervall an den Grenzen mit dem PRP-Test nachholen und seperat Entscheidungen vornehmen...Im Abteil "Thread9" oben im Code, wird das behandelt.
_________________
Umfangreichste Angaben zu Primzahl k-Tupel
https://www.pzktupel.de/ktuplets.php
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4594
Wohnort: ~/

BeitragVerfasst am: 07.12.2022, 17:35    Titel: Antworten mit Zitat

Code:
Dim T_ID(3) as Any Ptr
SLEEP 100:id=0:T_ID(0) = ThreadCreate(@MyThread)
SLEEP 100:id=1:T_ID(1) = ThreadCreate(@MyThread)
SLEEP 100:id=2:T_ID(2) = ThreadCreate(@MyThread)
SLEEP 100:id=3:T_ID(3) = ThreadCreate(@MyThread)

hat noch einen Nachteil: Nach dem Starten von Thread Nr. 0 laufen dieser Thread und das Hauptprogramm parallel, und im Prinzip könnte das Hauptprogramm die Variable schon neu gesetzt haben, bevor sie im Thread ausgelesen wird. Das wird durch das SLEEP 100 zwar unwahrscheinlich gemacht, allerdings hat das ein bisschen was von Finger kreuzen und Daumen drücken.

Der Parameter wird als ANY PTR übergeben; da ist die deutsche Referenz wohl inzwischen veraltet. Einen Pointer zu übergeben stellt dich natürlich vor dasselbe grundsätzliche Problem, dass bei Änderung der Variable im Hauptprogramm auch ein Seiteneffekt im Thread auftun kann. Allerdings kann man auch immer noch mit vier verschiedenen Variablen arbeiten, die sich gegenseitig nicht in die Quere kommen (oder man wartet auf eine Bestätigung des Threads, dass er erfolgreich initialisiert wurde).

Hier der englische Artikel zu THREADCREATE:
https://www.freebasic.net/wiki/KeyPgThreadCreate
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 81

BeitragVerfasst am: 07.12.2022, 18:35    Titel: Antworten mit Zitat

Ich erhalte immer einen Fehler beim kompilieren
> 2GAP1mu_tpmb.bas(214) error 28: Expected pointer, before ')' in 'T_ID(ix) = ThreadCreate(@MyThread,CPtr(Any Ptr, ix))' <

Ich habe doch das alles so 1:1 übertragen....

Code:

Sub MyThread (ByVal userdata as Any Ptr)
DIM AS ULONG MAS,P,U,q1,gb,AD
Dim As Integer id = CInt(userdata)
gb=id
P=0
WHILE P<maxs
P=PZ(gb):MAS=MA(gb)
U=P-((TS-MAS*O) MOD P)
q1=(U+(MAS SHL 1)) MOD P

     AD = 0
   WHILE (AD + P) < 50000300
      A(( U + AD) SHR 3) = BITSET(A(( U + AD) SHR 3), ( U + AD) MOD 8)
      A((q1 + AD) SHR 3) = BITSET(A((q1 + AD) SHR 3), (q1 + AD) MOD 8)
      AD += P
   WEND
   IF ( U + AD) < 50000300 THEN A(( U + AD) SHR 3) = BITSET(A(( U + AD) SHR 3), ( U + AD) MOD 8)
   IF (q1 + AD) < 50000300 THEN A((q1 + AD) SHR 3) = BITSET(A((q1 + AD) SHR 3), (q1 + AD) MOD 8)
   gb += 4

WEND
END sub
...
Dim as Any Ptr T_ID(0 to 3)
FOR ix AS UBYTE = 0 TO 3
T_ID(ix) = ThreadCreate(@MyThread,CPtr(Any Ptr, ix))
NEXT ix

_________________
Umfangreichste Angaben zu Primzahl k-Tupel
https://www.pzktupel.de/ktuplets.php
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
hhr



Anmeldungsdatum: 15.07.2020
Beiträge: 84

BeitragVerfasst am: 07.12.2022, 21:33    Titel: Antworten mit Zitat

Versuch mal Ulong anstelle von Ubyte:

FOR ix AS ULONG = 0 TO 3
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 81

BeitragVerfasst am: 07.12.2022, 21:50    Titel: Antworten mit Zitat

Selbige Fehlermeldung
error 28: Expected pointer, before ')' in 'T_ID(ix) = ThreadCreate(@MyThread,CPtr(Any Ptr, ix))'
_________________
Umfangreichste Angaben zu Primzahl k-Tupel
https://www.pzktupel.de/ktuplets.php
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
hhr



Anmeldungsdatum: 15.07.2020
Beiträge: 84

BeitragVerfasst am: 07.12.2022, 22:00    Titel: Antworten mit Zitat

Bei 32 Bit funktioniert Ulong, bei 64 Bit Ulongint im Beispielprogramm der Dokumentation. Vielleicht sollte man deshalb Integer wählen.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite 1, 2  Weiter
Seite 1 von 2

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

 Impressum :: Datenschutz