| 
				
					|  | Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
 |  
 
	
		| Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |  
		| Autor | Nachricht |  
		| pzktupel 
 
  
 Anmeldungsdatum: 07.07.2020
 Beiträge: 85
 
 
 | 
			
				|  Verfasst am: 02.12.2022, 17:23    Titel: Massives Problem im Primsieb |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| nemored 
 
  
 Anmeldungsdatum: 22.02.2007
 Beiträge: 4710
 Wohnort: ~/
 
 | 
			
				|  Verfasst am: 02.12.2022, 20:22    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| pzktupel 
 
  
 Anmeldungsdatum: 07.07.2020
 Beiträge: 85
 
 
 | 
			
				|  Verfasst am: 03.12.2022, 07:12    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| pzktupel 
 
  
 Anmeldungsdatum: 07.07.2020
 Beiträge: 85
 
 
 | 
			
				|  Verfasst am: 05.12.2022, 20:22    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| nemored 
 
  
 Anmeldungsdatum: 22.02.2007
 Beiträge: 4710
 Wohnort: ~/
 
 | 
			
				|  Verfasst am: 05.12.2022, 21:21    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| ThePuppetMaster 
 
  
 Anmeldungsdatum: 18.02.2007
 Beiträge: 1839
 Wohnort: [JN58JR]
 
 |  |  
		| Nach oben |  |  
		|  |  
		| pzktupel 
 
  
 Anmeldungsdatum: 07.07.2020
 Beiträge: 85
 
 
 | 
			
				|  Verfasst am: 06.12.2022, 06:29    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| ThePuppetMaster 
 
  
 Anmeldungsdatum: 18.02.2007
 Beiträge: 1839
 Wohnort: [JN58JR]
 
 | 
			
				|  Verfasst am: 06.12.2022, 13:24    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| pzktupel 
 
  
 Anmeldungsdatum: 07.07.2020
 Beiträge: 85
 
 
 | 
			
				|  Verfasst am: 06.12.2022, 14:46    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| ThePuppetMaster 
 
  
 Anmeldungsdatum: 18.02.2007
 Beiträge: 1839
 Wohnort: [JN58JR]
 
 |  |  
		| Nach oben |  |  
		|  |  
		| nemored 
 
  
 Anmeldungsdatum: 22.02.2007
 Beiträge: 4710
 Wohnort: ~/
 
 | 
			
				|  Verfasst am: 06.12.2022, 19:37    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| pzktupel 
 
  
 Anmeldungsdatum: 07.07.2020
 Beiträge: 85
 
 
 | 
			
				|  Verfasst am: 06.12.2022, 21:46    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| ThePuppetMaster 
 
  
 Anmeldungsdatum: 18.02.2007
 Beiträge: 1839
 Wohnort: [JN58JR]
 
 | 
			
				|  Verfasst am: 06.12.2022, 23:19    Titel: |   |  
				| 
 |  
				| 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
   
 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 |  |  
		|  |  
		| pzktupel 
 
  
 Anmeldungsdatum: 07.07.2020
 Beiträge: 85
 
 
 | 
			
				|  Verfasst am: 07.12.2022, 07:11    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| pzktupel 
 
  
 Anmeldungsdatum: 07.07.2020
 Beiträge: 85
 
 
 | 
			
				|  Verfasst am: 07.12.2022, 15:04    Titel: |   |  
				| 
 |  
				| 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
  ... 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 |  |  
		|  |  
		| nemored 
 
  
 Anmeldungsdatum: 22.02.2007
 Beiträge: 4710
 Wohnort: ~/
 
 | 
			
				|  Verfasst am: 07.12.2022, 17:35    Titel: |   |  
				| 
 |  
				|  	  | 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 |  |  
		|  |  
		| pzktupel 
 
  
 Anmeldungsdatum: 07.07.2020
 Beiträge: 85
 
 
 | 
			
				|  Verfasst am: 07.12.2022, 18:35    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| hhr 
 
 
 Anmeldungsdatum: 15.07.2020
 Beiträge: 116
 
 
 | 
			
				|  Verfasst am: 07.12.2022, 21:33    Titel: |   |  
				| 
 |  
				| Versuch mal Ulong anstelle von Ubyte: 
 FOR ix AS ULONG = 0 TO 3
 |  |  
		| Nach oben |  |  
		|  |  
		| pzktupel 
 
  
 Anmeldungsdatum: 07.07.2020
 Beiträge: 85
 
 
 | 
			
				|  Verfasst am: 07.12.2022, 21:50    Titel: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| hhr 
 
 
 Anmeldungsdatum: 15.07.2020
 Beiträge: 116
 
 
 | 
			
				|  Verfasst am: 07.12.2022, 22:00    Titel: |   |  
				| 
 |  
				| Bei 32 Bit funktioniert Ulong, bei 64 Bit Ulongint im Beispielprogramm der Dokumentation. Vielleicht sollte man deshalb Integer wählen. |  |  
		| Nach oben |  |  
		|  |  
		|  |  
  
	| 
 
 | 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.
 
 |  |