Windows Vista? *NEVER* Het waarom - Opera forever!!!
I've seen chickens that were more menacing. Chickens in a coma. On ice. In my fridge.
De logica met 2 semaphores is goed, als je slechts 1 producer en 1 consumer hebt.
Ik heb inderdaad maar slechts 1 producer en 1 consumer, meer is ook niet nodig. 'usage' geeft aan hoeveel van de buffer in gebruik is. Bij 0 is de buffer leeg, als het gelijk is aan 'bufsize', is de buffer vol. Als ik een element toevoeg dan komt er eentje bij, als ik er eentje lees gaat er eentje af.quote:Zoijar schreef op maandag 07 juli 2008 @ 20:25:
Wat is dat usage? Is dat thread-safe?
De logica met 2 semaphores is goed, als je slechts 1 producer en 1 consumer hebt.
Hoe weet ik of het thread-safe is?
Windows Vista? *NEVER* Het waarom - Opera forever!!!
I've seen chickens that were more menacing. Chickens in a coma. On ice. In my fridge.
Ik heb toevallig net zelf een shared memeory producer consumer buffer geschreven. Mijn acquire-release ziet er zo uit:
C++:
1 | T* acquire_write_slot(bool block = true) {
|
(ik split die functies omdat ik slots uitgeef en dat gaat via een scoped locking object... ingewikkeld... Verder gebruik ik boost::interprocess semaphores) Je kan nu iets toevoegen op deze manier:
C++:
1 | T* x = pcb->acquire_read_slot(true);
|
Wat mij wel nogal vreemd blijft is het volgende:
Als ik de programma run krijg ik heel vaak een error bij ReleaseSemaphore; 298. Dit is dat de semaphore te vaak is gereleased. Het zou maar een keer mogen, maar kennelijk gebeurt het vaker. Als ik naar de code kijk dan moet het toch correct zijn? Ik doe alleen maar een release bijvoorbeeld als 'usage == 1' en niet anders. Overflowen kan die waarde ook niet want als het gelijk is aan bufsize moet de producer wachten. Er wordt door de consumer heel mooi gewacht op de semaphore bij een lege buffer... wat is er nou mis? Hoe kan er toch dan deze disrepancy ontstaan?
Ook bizar is het feit dat kennelijk de correlatie coefficient van een vector van lengte 200 sneller berekend wordt dan een fprintf? Naja, als dat zo is...
Mijn code zoals die nu is:
Aanroepen threads:
C++:
1 | Wavelet w;
|
De threads zelf:
C++:
1 | typedef struct Wavelet {
|
Mijn buffer struct:
C++:
1 | /* $Id: buffer.h 70 2008-07-07 18:36:37Z tomi $ */
|
Windows Vista? *NEVER* Het waarom - Opera forever!!!
I've seen chickens that were more menacing. Chickens in a coma. On ice. In my fridge.
Dat verbaast me totaal niet eigenlijk. De berekening die je doet is puur een floating point operatie op een paar registers, dus daar walst de FPU lazy doorheen in de achtergrond terwijl de CPU al lang en breed op je synchronization object zit te walsen. Dit in vergelijk met fprintf die je adresbus zit te belasten voor het inlezen van de formatting string en vervolgens voor de output moet gaan zitten queuen op het veruit traagste onderdeel van je hele systeem.quote:Darkvater schreef op woensdag 09 juli 2008 @ 00:14:
Ook bizar is het feit dat kennelijk de correlatie coefficient van een vector van lengte 200 sneller berekend wordt dan een fprintf? Naja, als dat zo is...
Dit moet het zijn:
// Regels 9-10:
full = CreateSemaphore(NULL, 0, bufsize, NULL);
empty = CreateSemaphore(NULL, bufsize, bufsize, NULL);
// bufsize buckets max, full begint op 0, empty op bufsize
void Add(T p) {
WaitForSingleObject(empty, INFINITE);} // we hebben een EMPTY slot nodig hier!
this->buffer[write] = p;
write = increment(write);
usage++;
ReleaseSemaphore(full, 1,NULL); // we notify-en hier een FULL slot, nl. die we net hebben gevuld.
}
T Remove(void) {
WaitForSingleObject(full, INFINITE); // we hebben een FULL slot nodig hier!
T result = this->buffer[read];
read = increment(read);
usage--;
ReleaseSemaphore(empty, 1, NULL); // we krijgen er een EMPTY slot bij, we halen er eentje weg hier
return result;
}
Dit gaat goed bij een buffersize van 50, zoals in mijn code. Als ik dit echter verander naar 2 dan krijg ik een hele waslijst aan errors voor ReleaseSemaphore(empty) (Remove). Bij een buffersize van 1 krijg ik bij beiden ReleaseSemaphore(empty) (Remove) en ReleaseSemaphore(full) (Add) errors.
Iets klopt er nog steeds niet...
Windows Vista? *NEVER* Het waarom - Opera forever!!!
I've seen chickens that were more menacing. Chickens in a coma. On ice. In my fridge.
Krijg je dan geen problemen dat ReleaseSemaphore dan niet op het juiste moment wordt aangeroepen doordat een andere thread usage daarvoor ook veranderd heeft waardoor mogelijk een deadlock kan ontstaan?quote:.oisyn schreef op woensdag 09 juli 2008 @ 11:18:
Ik zou die critical sections sowieso niet gebruiken, het enige wat je ermee doet is de 'usage' variabele guarden die je alleen maar wilt incrementen en decrementen. Gebruik dan InterlockedIncrement() en InterlockedDecrement(), die zijn gegarandeerd atomic op elk systeem (en dus lockless en daarmee een stuk sneller dan zo'n synchronisatie-object).
Windows Vista? *NEVER* Het waarom - Opera forever!!!
I've seen chickens that were more menacing. Chickens in a coma. On ice. In my fridge.
Edit: DOH, ik snap nu wat Zoijar bedoelt. Haal die hele van 'while (usage == 0)' en '(while (usage == bufsize)'. Of eigenlijk de hele usage variabele en doe het met de semaphores
Op mijn manier is het eigenlijk een mutex, of zou het moeten zijn, maar werkt niet echt zo
Darkvater wijzigde dit bericht 09-07-2008 13:02 (69%)
Reden: he has seen the light!
Windows Vista? *NEVER* Het waarom - Opera forever!!!
I've seen chickens that were more menacing. Chickens in a coma. On ice. In my fridge.
Pagina: 1

