EDIT: Ab und zu bekomme ich einen IMA bei "WaitSemaphore(\doneSema)"
Multi Threads
Re: Multi Threads
Wow, danke Nic, läuft genauso wie es soll. 
EDIT: Ab und zu bekomme ich einen IMA bei "WaitSemaphore(\doneSema)"
EDIT: Ab und zu bekomme ich einen IMA bei "WaitSemaphore(\doneSema)"
PureBasic 5.46 LTS (Windows x86/x64) | windows 10 x64 Oktober failure
- NicTheQuick
- Ein Admin
- Beiträge: 8838
- Registriert: 29.08.2004 20:20
- Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
Re: Multi Threads
Hast du Thread-Unterstützung aktiviert?
Re: Multi Threads
Oh, das wars, mit Thread safe läuft es perfekt 
PureBasic 5.46 LTS (Windows x86/x64) | windows 10 x64 Oktober failure
- NicTheQuick
- Ein Admin
- Beiträge: 8838
- Registriert: 29.08.2004 20:20
- Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
Re: Multi Threads
Das freut mich. Übrigens kannst du auch zwischendrin neue Aufgaben mit addThread(*block, @proc()) hinzufügen. Beim nächsten Aufruf von processBlock() wird dann auch diese Aufgabe ausgeführt.
Und vergiss am Ende das destroyBlock(*block) nicht.
Und vergiss am Ende das destroyBlock(*block) nicht.
- ts-soft
- Beiträge: 22292
- Registriert: 08.09.2004 00:57
- Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel - Wohnort: Berlin
Re: Multi Threads
Dann steht ja dem nächstem Kartoffelgratin nichts mehr im Wege 
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

Re: Multi Threads
Dein Code is echt genial Nic, nochmals Danke.
Ich habe mal ein praktisches Beispiel mit PB's Fingerprint Funktion erstellt.
Mit den Threads läuft es hier ungefähr doppelt so schnell als ohne.
Ich habe mal ein praktisches Beispiel mit PB's Fingerprint Funktion erstellt.
Mit den Threads läuft es hier ungefähr doppelt so schnell als ohne.
Code: Alles auswählen
EnableExplicit
Define *Buffer, iRead, x, sfile.s, CRC$, MD5$, SHA1$
#Buffersize = 8192
Prototype Aufgabe(*buffer, bufferSize.i, iBlock.i)
UseCRC32Fingerprint()
UseMD5Fingerprint()
UseSHA1Fingerprint()
Structure Block
*buffer ; Pointer zum Puffer selbst
size.i ; Größe des Puffers
iBlock.i ; Nummer des Blocks
waitSema.i ; Semaphore um auf Befüllen den Blockes zu warten
doneSema.i ; Semaphore um auf Beendigung der Verarbeitung zu warten
allDoneSema.i ;
stop.i ; #True, wenn der Thread sich beenden soll
List threads.i()
cThreads.i ; Anzahl der Threads
EndStructure
Procedure.i newBlock()
Protected *block.Block = AllocateStructure(Block)
With *block
\waitSema = CreateSemaphore()
\doneSema = CreateSemaphore()
\allDoneSema = CreateSemaphore()
EndWith
ProcedureReturn *block
EndProcedure
Structure ThreadData
*block.Block
aufgabe.Aufgabe
EndStructure
Procedure AufgabeThread(*data.ThreadData)
With *data\block
Repeat
; Warte bis ein neuer Block da ist
WaitSemaphore(\waitSema)
If \stop
Break
EndIf
; Führe die Aufgabe auf dem Block aus
*data\aufgabe(\buffer, \size, \iBlock)
; Melde dem Hauptthread, dass du fertig bist
SignalSemaphore(\doneSema)
; Warte auf den Hauptthread, der dir mitteilt, das alle anderen Threads auch fertig sind
WaitSemaphore(\allDoneSema)
ForEver
EndWith
FreeStructure(*data)
EndProcedure
Procedure.i addThread(*block.Block, aufgabe.Aufgabe)
Protected thread.i
Protected *threadData.ThreadData = AllocateStructure(ThreadData)
If Not *threadData
ProcedureReturn #False
EndIf
With *block
*threadData\block = *block
*threadData\aufgabe = aufgabe
If AddElement(\threads())
\threads() = CreateThread(@AufgabeThread(), *threadData)
If Not \threads()
FreeStructure(*threadData)
DeleteElement(\threads())
EndIf
Else
FreeStructure(*threadData)
ProcedureReturn #False
EndIf
\cThreads = ListSize(\threads())
EndWith
ProcedureReturn #True
EndProcedure
Procedure.i processBlock(*block.Block, *buffer, bufferSize.i, iBlock.i)
Protected i.i
With *block
\buffer = *buffer
\size = bufferSize
\iBlock = iBlock
; Sage allen Threads, dass sie ihre Arbeit beginnen sollen
For i = 1 To \cThreads
SignalSemaphore(\waitSema)
Next
; Warte, bis alle Threads fertig sind
For i = 1 To \cThreads
WaitSemaphore(\doneSema)
Next
; Melde allen Threads, das nun alle fertig sind und auf neue Arbeit warten können.
For i = 1 To \cThreads
SignalSemaphore(\allDoneSema)
Next
EndWith
EndProcedure
Procedure.i destroyBlock(*block.Block)
Protected i
With *block
\stop = #True
; Sage allen Threads, dass sie sich beenden sollen
For i = 1 To \cThreads
SignalSemaphore(\waitSema)
Next
; Warte auf Beendigung der Threads
ForEach \threads()
WaitThread(\threads())
Next
FreeSemaphore(\waitSema)
FreeSemaphore(\doneSema)
FreeSemaphore(\allDoneSema)
EndWith
FreeStructure(*block)
EndProcedure
; ============== Hauptprogramm ===============
Procedure Aufgabe1(*Buffer, BufferSize, iBlock)
;Debug "Aufgabe1 bearbeitet Block: " + iBlock + " "
AddFingerprintBuffer(0, *Buffer, BufferSize)
EndProcedure
Procedure Aufgabe2(*Buffer, BufferSize, iBlock)
;Debug "Aufgabe2 bearbeitet Block: " + iBlock
AddFingerprintBuffer(1, *Buffer, BufferSize)
EndProcedure
Procedure Aufgabe3(*Buffer, BufferSize, iBlock)
;Debug "Aufgabe3 bearbeitet Block: " + iBlock
AddFingerprintBuffer(2, *Buffer, BufferSize)
EndProcedure
Define.Block *block = newBlock()
StartFingerprint(0, #PB_Cipher_CRC32)
StartFingerprint(1, #PB_Cipher_MD5)
StartFingerprint(2, #PB_Cipher_SHA1)
addThread(*block, @Aufgabe1())
addThread(*block, @Aufgabe2())
addThread(*block, @Aufgabe3())
*buffer = AllocateMemory(#Buffersize)
If Not *buffer
End
EndIf
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
sfile = #PB_Compiler_Home + "PureBasic.exe"
CompilerDefault
sfile = #PB_Compiler_Home + "compilers/PureBasic"
CompilerEndSelect
If ReadFile(0, sfile)
While Not Eof(0)
iRead = ReadData(0, *buffer, #Buffersize)
x + 1
processBlock(*block, *buffer, iRead, x)
;Debug "============================"
Wend
CloseFile(0)
EndIf
FreeMemory(*buffer)
destroyBlock(*block)
Debug "Checksum of file: " + sfile + #CRLF$
CRC$ = FinishFingerprint(0) ; finish calculation
Debug "CRC32 checksum" + #TAB$ + " = " + CRC$
MD5$ = FinishFingerprint(1) ; finish calculation
Debug "MD5 checksum" + #TAB$ + " = " + MD5$
SHA1$ = FinishFingerprint(2) ; finish calculation
Debug "SHA1 checksum" + #TAB$ + " = " + SHA1$
PureBasic 5.46 LTS (Windows x86/x64) | windows 10 x64 Oktober failure
- NicTheQuick
- Ein Admin
- Beiträge: 8838
- Registriert: 29.08.2004 20:20
- Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
Re: Multi Threads
Mit den Fingerprints habe ich das Teil auch getestet.
Geht aber echt gut. Dauert ca 17 Sekunden für eine 2,4 GB Datei, wobei ich noch SHA2 und SHA3 mit eingebaut habe. Wenn man die #BufferSize mal 1024 macht, bringt es auch noch einen guten Schub. Mit 8 kB Buffer dauert es fast doppelt so lange.
Wer hat Lust auf einen Contest? Man müsste sich nur noch auf die Datengröße einigen, die wir dafür nutzen. 
Geht aber echt gut. Dauert ca 17 Sekunden für eine 2,4 GB Datei, wobei ich noch SHA2 und SHA3 mit eingebaut habe. Wenn man die #BufferSize mal 1024 macht, bringt es auch noch einen guten Schub. Mit 8 kB Buffer dauert es fast doppelt so lange.
Code: Alles auswählen
EnableExplicit
Define *Buffer, iRead, x, sfile.s, CRC$, MD5$, SHA1$, SHA2$, SHA3$
#Buffersize = 8192 * 1024
Prototype Aufgabe(*buffer, bufferSize.i, iBlock.i)
UseCRC32Fingerprint()
UseMD5Fingerprint()
UseSHA1Fingerprint()
UseSHA2Fingerprint()
UseSHA3Fingerprint()
Structure Block
*buffer ; Pointer zum Puffer selbst
size.i ; Größe des Puffers
iBlock.i ; Nummer des Blocks
waitSema.i ; Semaphore um auf Befüllen den Blockes zu warten
doneSema.i ; Semaphore um auf Beendigung der Verarbeitung zu warten
allDoneSema.i ;
stop.i ; #True, wenn der Thread sich beenden soll
List threads.i()
cThreads.i ; Anzahl der Threads
EndStructure
Procedure.i newBlock()
Protected *block.Block = AllocateStructure(Block)
With *block
\waitSema = CreateSemaphore()
\doneSema = CreateSemaphore()
\allDoneSema = CreateSemaphore()
EndWith
ProcedureReturn *block
EndProcedure
Structure ThreadData
*block.Block
aufgabe.Aufgabe
EndStructure
Procedure AufgabeThread(*data.ThreadData)
With *data\block
Repeat
; Warte bis ein neuer Block da ist
WaitSemaphore(\waitSema)
If \stop
Break
EndIf
; Führe die Aufgabe auf dem Block aus
*data\aufgabe(\buffer, \size, \iBlock)
; Melde dem Hauptthread, dass du fertig bist
SignalSemaphore(\doneSema)
; Warte auf den Hauptthread, der dir mitteilt, das alle anderen Threads auch fertig sind
WaitSemaphore(\allDoneSema)
ForEver
EndWith
FreeStructure(*data)
EndProcedure
Procedure.i addThread(*block.Block, aufgabe.Aufgabe)
Protected thread.i
Protected *threadData.ThreadData = AllocateStructure(ThreadData)
If Not *threadData
ProcedureReturn #False
EndIf
With *block
*threadData\block = *block
*threadData\aufgabe = aufgabe
If AddElement(\threads())
\threads() = CreateThread(@AufgabeThread(), *threadData)
If Not \threads()
FreeStructure(*threadData)
DeleteElement(\threads())
EndIf
Else
FreeStructure(*threadData)
ProcedureReturn #False
EndIf
\cThreads = ListSize(\threads())
EndWith
ProcedureReturn #True
EndProcedure
Procedure.i processBlock(*block.Block, *buffer, bufferSize.i, iBlock.i)
Protected i.i
With *block
\buffer = *buffer
\size = bufferSize
\iBlock = iBlock
; Sage allen Threads, dass sie ihre Arbeit beginnen sollen
For i = 1 To \cThreads
SignalSemaphore(\waitSema)
Next
; Warte, bis alle Threads fertig sind
For i = 1 To \cThreads
WaitSemaphore(\doneSema)
Next
; Melde allen Threads, das nun alle fertig sind und auf neue Arbeit warten können.
For i = 1 To \cThreads
SignalSemaphore(\allDoneSema)
Next
EndWith
EndProcedure
Procedure.i destroyBlock(*block.Block)
Protected i
With *block
\stop = #True
; Sage allen Threads, dass sie sich beenden sollen
For i = 1 To \cThreads
SignalSemaphore(\waitSema)
Next
; Warte auf Beendigung der Threads
ForEach \threads()
WaitThread(\threads())
Next
FreeSemaphore(\waitSema)
FreeSemaphore(\doneSema)
FreeSemaphore(\allDoneSema)
EndWith
FreeStructure(*block)
EndProcedure
; ============== Hauptprogramm ===============
Procedure HashCRC32(*Buffer, BufferSize, iBlock)
AddFingerprintBuffer(0, *Buffer, BufferSize)
EndProcedure
Procedure HashMD5(*Buffer, BufferSize, iBlock)
AddFingerprintBuffer(1, *Buffer, BufferSize)
EndProcedure
Procedure HashSHA1(*Buffer, BufferSize, iBlock)
AddFingerprintBuffer(2, *Buffer, BufferSize)
EndProcedure
Procedure HashSHA2(*Buffer, BufferSize, iBlock)
AddFingerprintBuffer(2, *Buffer, BufferSize)
EndProcedure
Procedure HashSHA3(*Buffer, BufferSize, iBlock)
AddFingerprintBuffer(2, *Buffer, BufferSize)
EndProcedure
Define.Block *block = newBlock()
StartFingerprint(0, #PB_Cipher_CRC32)
StartFingerprint(1, #PB_Cipher_MD5)
StartFingerprint(2, #PB_Cipher_SHA1)
StartFingerprint(3, #PB_Cipher_SHA2, 512)
StartFingerprint(4, #PB_Cipher_SHA3, 512)
addThread(*block, @HashCRC32())
addThread(*block, @HashMD5())
addThread(*block, @HashSHA1())
addThread(*block, @HashSHA2())
addThread(*block, @HashSHA3())
*buffer = AllocateMemory(#Buffersize)
If Not *buffer
End
EndIf
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
sfile = #PB_Compiler_Home + "PureBasic.exe"
CompilerDefault
sfile = #PB_Compiler_Home + "compilers/PureBasic"
CompilerEndSelect
sfile = "/home/nicolas/Videos/MVI_7857.MOV"
Define time.i = ElapsedMilliseconds()
If ReadFile(0, sfile)
While Not Eof(0)
iRead = ReadData(0, *buffer, #Buffersize)
x + 1
processBlock(*block, *buffer, iRead, x)
Wend
CloseFile(0)
EndIf
FreeMemory(*buffer)
destroyBlock(*block)
CRC$ = FinishFingerprint(0)
MD5$ = FinishFingerprint(1)
SHA1$ = FinishFingerprint(2)
SHA2$ = FinishFingerprint(3)
SHA3$ = FinishFingerprint(4)
time = ElapsedMilliseconds() - time
Define.s result
result = "Checksum of file: " + sfile + #CRLF$ +
"CRC32 checksum" + #TAB$ + " = " + CRC$ + #CRLF$ +
"MD5 checksum" + #TAB$ + " = " + MD5$ + #CRLF$ +
"SHA1 checksum" + #TAB$ + " = " + SHA1$ + #CRLF$ +
"SHA2 checksum" + #TAB$ + " = " + SHA2$ + #CRLF$ +
"SHA3 checksum" + #TAB$ + " = " + SHA3$ + #CRLF$ +
"Time: " + StrD(time / 1000.0, 3) + " s"
SetClipboardText(result)
MessageRequester("Checksums", result)- xXRobo_CubeXx
- Beiträge: 120
- Registriert: 12.06.2015 16:08
- Computerausstattung: Version 5.41 LTS
- Wohnort: Wohnort
- Kontaktdaten:
Re: Multi Threads
Was ist der Unterschied zwischen CRC32Fingerprint, MD5Fingerprint und SHA1Fingerprint?
Nur andere Berechnungs Methoden? Gibt es auch Geschwindigkeitsunterschiede? Hat das einer getestet? Was ist das schnellste?
Danke fürs posten eurer Erfahrungen

Nur andere Berechnungs Methoden? Gibt es auch Geschwindigkeitsunterschiede? Hat das einer getestet? Was ist das schnellste?
Danke fürs posten eurer Erfahrungen
Version 5.41 LTS 
- NicTheQuick
- Ein Admin
- Beiträge: 8838
- Registriert: 29.08.2004 20:20
- Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
Re: Multi Threads
CRC32, MD5, SHA1, SHA2 und SHA3 sind alles verschieden starke Prüfsummenverfahren oder auch Hashverfahren.
Üblicherweise speichert man zum Beispiel das Passwort eines Users immer als Hash in der Datenbank. Will dieser sich einloggen, wird die Eingabe gehasht und dann gegen den Hash in der Datenbank verglichen. Jetzt ist es aber so, dass CRC32, MD5 und SHA1 alleine nicht mehr zu gebrauchen sind, weil die geknackt wurden, d.h. es ist in absehbarer Zeit möglich ein Passwort zu finden, das den selben Hash ergibt. Bei SHA2 und SHA3 sieht das anders aus.
Normalerweise geht es hier auch nicht darum, was der schnellste Hash ist, sondern wie kryptographisch sicher der Hash ist.
Aber um deine Frage zu beantworten: CRC32 ist am schnellsten.
Üblicherweise speichert man zum Beispiel das Passwort eines Users immer als Hash in der Datenbank. Will dieser sich einloggen, wird die Eingabe gehasht und dann gegen den Hash in der Datenbank verglichen. Jetzt ist es aber so, dass CRC32, MD5 und SHA1 alleine nicht mehr zu gebrauchen sind, weil die geknackt wurden, d.h. es ist in absehbarer Zeit möglich ein Passwort zu finden, das den selben Hash ergibt. Bei SHA2 und SHA3 sieht das anders aus.
Normalerweise geht es hier auch nicht darum, was der schnellste Hash ist, sondern wie kryptographisch sicher der Hash ist.
Aber um deine Frage zu beantworten: CRC32 ist am schnellsten.
Re: Multi Threads
es kommt halt darauf an, wozu du den Hash benutzen willst. Für Passwörter ist das klar. Wenn es aber bspw. darum geht, Übertragungsfehler rauszufinden, dürfte CRC32 deutlich praktischer sein.NicTheQuick hat geschrieben:Normalerweise geht es hier auch nicht darum, was der schnellste Hash ist, sondern wie kryptographisch sicher der Hash ist.
Aber um deine Frage zu beantworten: CRC32 ist am schnellsten.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!