Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Quando il thread verrà eseguito, nessuno ti garantisce che lo stack dell'altra funzione (quella che ha creato il thread) sia ancora consistente con il momento della creazione del thread, quindi se ti funziona è solo per botta di culo.
Alloca SEMPRE nell'heap i dati condivisi tra 2 thread.
Ultima modifica effettuata da TheKaneB il 14/01/2011 alle 3:32
il compilatore si incazza perchè tenti di fare un casting senza senso...
Codice sorgente - presumibilmente C++
void*fillMatrixWithSift(void*app){
struct matrix fill;
fill =&((struct matrix *) app);<--- riga 162.
constchar*file = fill.stringa;
int n = fill.dimensione;
int**val = fill.M;
così dovrebbe andare
Intendevi così ?
Codice sorgente - presumibilmente Plain Text
fill = *((struct matrix *) app);
In ogni caso non vedo quale sia l'utilità di copiare l'intera struct nello stack del thread, quando puoi usare direttamente il puntatore (ovviamente se non vuoi modificare il valore della struttura originale basta stare attenti: io avrei tolto la variabile fill e mi sarei portato dietro il casting).
Testo quotato
Quando il thread verrà eseguito, nessuno ti garantisce che lo stack dell'altra funzione (quella che ha creato il thread) sia ancora consistente con il momento della creazione del thread, quindi se ti funziona è solo per botta di culo.
Alloca SEMPRE nell'heap i dati condivisi tra 2 thread.
Penso che, a fine main, faccia un join, quindi grossi problemi non ce ne sono (classica programmazione universitaria, che quando cerchi di cambiare qualcosina, non funziona più un cavolo).
Ultima modifica effettuata da Xaratroom il 14/01/2011 alle 8:26
ho risolto così, inizialmente passavo per puntatore fill solo che per accedere ai campi usavo
Codice sorgente - presumibilmente Plain Text
fill.n = dimensione
e mi diceva che non era un operazione della struct matrix ma di matrix* ( un errore simile ora non ricordo benissimo ) così avevo tolto il puntatore a fill con risultato il suddetto errore
@ TheKaneB: non ho capito benissimo cosa intendi, io faccio la classica programmazione universitaria facendo la join nella funzione chiamante (qualsiasi consiglio per rimediare a ciò è ben accetto! )
@ Xaratroom: compilo così g++ -fopenmp -lpthread -o3 nome.c
supponiamo che venga creato il primo thread, questo entra in run ma subito lo scheduler decide che il suo timeslice è scaduto e passa il controllo nuovamente al main.
Il while fa un'altro ciclo, crea un nuovo oggetto "param", che nello stack avrà la stessa posizione del param dell'iterazione di prima, crea un nuovo thread e gli passa lo stesso indirizzo (in pratica passa sempre lo stesso indirizzo a tutti i thread).
Quando il primo thread si sarà svegliato, si ritroverà con il valore di "i" nuovo, anzichè quello precedente, perchè andando a leggere quell'indirizzo di memoria si ritroverà con dei dati sovrascritti dalla successiva iterazione del while.
La stessa cosa può accadere se, ad esempio, il thread viene assegnato ad un'altra CPU in un sistema multiprocessore/multicore, in modo tale da avere un parallelismo reale tra la creazione dei thread e i thread stessi.
Se il programma funziona è dovuto a queste 3 botte di culo combinate:
1) Lo scheduler lascia il nuovo thread in running per un periodo di tempo accettabile
2) Il thread arriva sempre a farsi una copia dei parametri, perchè lo fai nelle primissime istruzioni e quindi impiega poco tempo
3) Il thread viene spawnato sulla stessa CPU per massimizzare i cache hit di dati e istruzioni.
Queste 3 condizioni sono spesso vere, ma nessuno ti garantisce tale sicurezza.
In generale, quindi, è assolutamente vietato passare parametri ai thread usando lo stack.
Durante la creazione dei thread, fai semplicemente una new, o una malloc, allocando così la struct nell'heap. Poi dentro il thread stesso puoi tranquillamente fare la delete, o free, quando quell'oggetto non ti servirà più. In questo modo risolvi tutti i problemi.
@Xaratroom:
Testo quotato
Intendevi così ?
Codice sorgente - presumibilmente Plain Text
fill = *((struct matrix *) app);
si, grazie per la correzione, ho scritto al volo senza troppo pensarci :-p
Ultima modifica effettuata da TheKaneB il 14/01/2011 alle 18:44
in questo caso io ne creo solo due di thread e gli do il nome univoco di 0 al primo e 1 al secondo, ai due passo due strutture distinte che ognuno mette nel proprio stack.
Ho capito cosa intendi però credo di non avere questo problema (credo comunque )
in un'altra parte ho usato i thread e ho fatto così:
per come la vedo io, ognuno di questi 6 thread avrà indice nel proprio stack, ipotizzando che lo scheduler tolga le risorse al primo thread appena è stato creato e lo riporta al master questi proseguirà con il ciclo for facendo le sue cose incrementerà indice e creerà un nuovo thread a cui passa un altro indice. Ora il controllo ritorna al primo thread creato il quale prenderà dal suo stack l'indice che, da quello che ne ho capito, è in uno spazio differente dallo stack del secondo thread creato perciò non dovrebbero esserci problemi.
Quando il master esce dal for aspetta tutti gli altri thread prima di ricrearli per il ciclo while e quindi di volta in volta ognuno avrà un proprio indice univoco da passare al proprio job..no?
il primo caso è comunque errato (leggi il mio post precedente con molta attenzione). Il secondo è corretto. - TheKaneB - 14/01/11 21:13
in questo caso io ne creo solo due di thread e gli do il nome univoco di 0 al primo e 1 al secondo, ai due passo due strutture distinte che ognuno mette nel proprio stack.
Ho capito cosa intendi però credo di non avere questo problema (credo comunque )
in un'altra parte ho usato i thread e ho fatto così:
per come la vedo io, ognuno di questi 6 thread avrà indice nel proprio stack, ipotizzando che lo scheduler tolga le risorse al primo thread appena è stato creato e lo riporta al master questi proseguirà con il ciclo for facendo le sue cose incrementerà indice e creerà un nuovo thread a cui passa un altro indice. Ora il controllo ritorna al primo thread creato il quale prenderà dal suo stack l'indice che, da quello che ne ho capito, è in uno spazio differente dallo stack del secondo thread creato perciò non dovrebbero esserci problemi.
Quando il master esce dal for aspetta tutti gli altri thread prima di ricrearli per il ciclo while e quindi di volta in volta ognuno avrà un proprio indice univoco da passare al proprio job..no?
Funziona perché, come hai scritto anche tu, passi un valore intero nello spazio dedicato ad un indirizzo... Fortuna vuole che l'intero, in quello spazio, ci stia.
Se passi una variabile sullo stack, affinché il programma funzioni correttamente, devi assicurarti che quella variabile rimanga al suo posto per tutta l'esecuzione del thread.
Ma fate C o C++ ? perché compili come c++ se hai praticamente scritto codice C (dichiarazioni delle variabili a parte)