![Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht](misc/logos/logo.png) |
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
![](images/avatars/7516772835f10bc2830124.png)
Anmeldungsdatum: 07.07.2020 Beiträge: 83
|
Verfasst am: 02.12.2022, 18: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 |
|
![](templates/subSilver/images/spacer.gif) |
nemored
![](images/avatars/18585278245ddb8b9d8710.png)
Anmeldungsdatum: 22.02.2007 Beiträge: 4598 Wohnort: ~/
|
Verfasst am: 02.12.2022, 21: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 |
|
![](templates/subSilver/images/spacer.gif) |
pzktupel
![](images/avatars/7516772835f10bc2830124.png)
Anmeldungsdatum: 07.07.2020 Beiträge: 83
|
Verfasst am: 03.12.2022, 08: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 |
|
![](templates/subSilver/images/spacer.gif) |
pzktupel
![](images/avatars/7516772835f10bc2830124.png)
Anmeldungsdatum: 07.07.2020 Beiträge: 83
|
Verfasst am: 05.12.2022, 21: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 |
|
![](templates/subSilver/images/spacer.gif) |
nemored
![](images/avatars/18585278245ddb8b9d8710.png)
Anmeldungsdatum: 22.02.2007 Beiträge: 4598 Wohnort: ~/
|
Verfasst am: 05.12.2022, 22: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 |
|
![](templates/subSilver/images/spacer.gif) |
ThePuppetMaster
![](images/avatars/15203237124744b0302dc46.gif)
Anmeldungsdatum: 18.02.2007 Beiträge: 1837 Wohnort: [JN58JR]
|
|
Nach oben |
|
![](templates/subSilver/images/spacer.gif) |
pzktupel
![](images/avatars/7516772835f10bc2830124.png)
Anmeldungsdatum: 07.07.2020 Beiträge: 83
|
Verfasst am: 06.12.2022, 07: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, 15:53, insgesamt 2-mal bearbeitet |
|
Nach oben |
|
![](templates/subSilver/images/spacer.gif) |
ThePuppetMaster
![](images/avatars/15203237124744b0302dc46.gif)
Anmeldungsdatum: 18.02.2007 Beiträge: 1837 Wohnort: [JN58JR]
|
Verfasst am: 06.12.2022, 14: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 |
|
![](templates/subSilver/images/spacer.gif) |
pzktupel
![](images/avatars/7516772835f10bc2830124.png)
Anmeldungsdatum: 07.07.2020 Beiträge: 83
|
Verfasst am: 06.12.2022, 15: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 |
|
![](templates/subSilver/images/spacer.gif) |
ThePuppetMaster
![](images/avatars/15203237124744b0302dc46.gif)
Anmeldungsdatum: 18.02.2007 Beiträge: 1837 Wohnort: [JN58JR]
|
|
Nach oben |
|
![](templates/subSilver/images/spacer.gif) |
nemored
![](images/avatars/18585278245ddb8b9d8710.png)
Anmeldungsdatum: 22.02.2007 Beiträge: 4598 Wohnort: ~/
|
Verfasst am: 06.12.2022, 20: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 |
|
![](templates/subSilver/images/spacer.gif) |
pzktupel
![](images/avatars/7516772835f10bc2830124.png)
Anmeldungsdatum: 07.07.2020 Beiträge: 83
|
Verfasst am: 06.12.2022, 22: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 |
|
![](templates/subSilver/images/spacer.gif) |
ThePuppetMaster
![](images/avatars/15203237124744b0302dc46.gif)
Anmeldungsdatum: 18.02.2007 Beiträge: 1837 Wohnort: [JN58JR]
|
Verfasst am: 07.12.2022, 00: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 |
|
![](templates/subSilver/images/spacer.gif) |
pzktupel
![](images/avatars/7516772835f10bc2830124.png)
Anmeldungsdatum: 07.07.2020 Beiträge: 83
|
Verfasst am: 07.12.2022, 08: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 |
|
![](templates/subSilver/images/spacer.gif) |
pzktupel
![](images/avatars/7516772835f10bc2830124.png)
Anmeldungsdatum: 07.07.2020 Beiträge: 83
|
Verfasst am: 07.12.2022, 16: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 |
|
![](templates/subSilver/images/spacer.gif) |
nemored
![](images/avatars/18585278245ddb8b9d8710.png)
Anmeldungsdatum: 22.02.2007 Beiträge: 4598 Wohnort: ~/
|
Verfasst am: 07.12.2022, 18: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 |
|
![](templates/subSilver/images/spacer.gif) |
pzktupel
![](images/avatars/7516772835f10bc2830124.png)
Anmeldungsdatum: 07.07.2020 Beiträge: 83
|
Verfasst am: 07.12.2022, 19: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 |
|
![](templates/subSilver/images/spacer.gif) |
hhr
Anmeldungsdatum: 15.07.2020 Beiträge: 89
|
Verfasst am: 07.12.2022, 22:33 Titel: |
|
|
Versuch mal Ulong anstelle von Ubyte:
FOR ix AS ULONG = 0 TO 3 |
|
Nach oben |
|
![](templates/subSilver/images/spacer.gif) |
pzktupel
![](images/avatars/7516772835f10bc2830124.png)
Anmeldungsdatum: 07.07.2020 Beiträge: 83
|
Verfasst am: 07.12.2022, 22: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 |
|
![](templates/subSilver/images/spacer.gif) |
hhr
Anmeldungsdatum: 15.07.2020 Beiträge: 89
|
Verfasst am: 07.12.2022, 23:00 Titel: |
|
|
Bei 32 Bit funktioniert Ulong, bei 64 Bit Ulongint im Beispielprogramm der Dokumentation. Vielleicht sollte man deshalb Integer wählen. |
|
Nach oben |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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.
|
|