Thodoris21 Δημοσιεύτηκε Ιούνιος 6, 2012 #1 Κοινοποίηση Δημοσιεύτηκε Ιούνιος 6, 2012 Καλησπέρα.Θέλω να περάσω μεταβλητές στην pthread_create η οποία καλεί μια συνάρτηση που εκτελεί κάθε thread.Το πρόβλημα είναι οτι μέσω της pthread_create δεν μπορώ να περάσω πάνω από μια μεταβλητές.Υπάρχει κάποιος τρόπος εκτός από την χρήση structs?Ευχαριστώ. Link to comment Share on other sites More sharing options...
nucleus Ιούνιος 6, 2012 #2 Κοινοποίηση Ιούνιος 6, 2012 Αν δεν κάνω λάθος περνάς το ορίσματα στην συνάρτηση που θα εκτελέσει το thread.void *arg δεν μπορείς εκεί να περάσεις πίνακα με τα ορίσματα ή struct όπως είπες?προσοχή στις global μεταβλητές Link to comment Share on other sites More sharing options...
Thodoris21 Ιούνιος 6, 2012 Author #3 Κοινοποίηση Ιούνιος 6, 2012 Η pthread_create σου δίνει την δυνατότητα να περάσεις ένα όρισμα ή έναν δείκτη σε μια struct.Δοκίμασα με struct αλλά κάποια ορίσματα παίζουν και άλλα χτυπάνε.Επίσης δεν μπορώ πως περνάω πίνακες στην struct.Γενικά έχω πρόβλημα με τις μεταβλητές. Link to comment Share on other sites More sharing options...
nucleus Ιούνιος 6, 2012 #4 Κοινοποίηση Ιούνιος 6, 2012 pthread_create(3): create new thread - Linux man pageστον κώδικα του παραδείγματος- δομή για ορίσματα που θα περάσεις στην συνάρτηση που θα εκτελει το threadstruct thread_info { /* Used as argument to thread_start() */ pthread_t thread_id; /* ID returned by pthread_create() */ int thread_num; /* Application-defined thread # */ char *argv_string; /* From command-line argument */};- συνάρτηση που θα εκτελέσει το threadstatic void *thread_start(void *arg){ struct thread_info *tinfo = (struct thread_info *) arg; char *uargv, *p; printf("Thread %d: top of stack near %p; argv_string=%s\n", tinfo->thread_num, &p, tinfo->argv_string); uargv = strdup(tinfo->argv_string); if (uargv == NULL) handle_error("strdup"); for (p = uargv; *p != '\0'; p++) *p = toupper(*p); return uargv;} - δημιουργία threads (προσοχη στο πως καλείται η pthread_create) s = pthread_create(&tinfo[tnum].thread_id, &attr,&thread_start, &tinfo[tnum]); Link to comment Share on other sites More sharing options...
Thodoris21 Ιούνιος 6, 2012 Author #5 Κοινοποίηση Ιούνιος 6, 2012 Κατι αντιστοιχο εχω κανει αλλα χτυπαει το προγραμμα.Βασικα εχω φτιαξει το σεριακο προγραμμα και πρεπει να το μετατρεψω σε παραλληλο χρησιμοποιωντας posix threads.Θα ποσταρα τον κωδικα αλλα ειναι 300 γραμμες! Link to comment Share on other sites More sharing options...
nucleus Ιούνιος 6, 2012 #6 Κοινοποίηση Ιούνιος 6, 2012 struct thread_info *tinfo = (struct thread_info *) arg;Σημαντικότατο cast στον κώδικα της thread_start Link to comment Share on other sites More sharing options...
Thodoris21 Ιούνιος 6, 2012 Author #7 Κοινοποίηση Ιούνιος 6, 2012 Το ίδιο έχω κάνει και εγώ...void *maps(void *arguments) {struct arg_struct *args = arguments;......Κάποιες παραμέτρους μπορώ να τις περάσω μέσω της struct αλλά έχω πρόβλημα με το πέρασμα των πινάκων! Link to comment Share on other sites More sharing options...
nucleus Ιούνιος 6, 2012 #8 Κοινοποίηση Ιούνιος 6, 2012 Όχι δεν κάνεις το ίδιο :Simplicit castvoid *maps(void *arguments) {struct arg_struct *args = arguments;......explicit caststruct arg_struct *args = (struct arg_struct *) arguments;Στο πρώτο λες στον compiler να κάνει την μετατροπή όσο καλύτερα μπορεί.Στην δεύτερη του λες συγκεριμένα σε τι τυπο θα κάνει την μετατροπή.πίνακες σαν members ενός structstruct thread_info { /* Used as argument to thread_start() */ char name[64]; char course[128]; int age; int year;};υποθέτω αυτό δουλεύει σαν αρχικοποίησηthread_info.name = {(64 στοιχεία χωρισμένα με κόμμα)} Link to comment Share on other sites More sharing options...
Thodoris21 Ιούνιος 6, 2012 Author #9 Κοινοποίηση Ιούνιος 6, 2012 Ναι αλλα επελεξα το πρωτο γιατι το προγραμμα ετρεχε.Με τον δευτερο τροπο που προτεινεις δεν επερνα λαθη στο compile αλλα segmantation fault στην εκτελεση! Link to comment Share on other sites More sharing options...
Jaco Ιούνιος 7, 2012 #10 Κοινοποίηση Ιούνιος 7, 2012 Καταρχήν ο pointer από τα δεδομένα που περνάς πρέπει να δείχνει μια θέση μνήμης στο heap memory space. Οπότε θα πρέπει να κάνεις allocation είτε με global μεταβλητές, είτε σε κάποιο static pointer.Δεύτερων, αν η μνήμη αυτή είναι κοινή για όλα τα threads τότε χρησιμοποιείς semaphores και mutexes όταν θες να έχεις πρόσβαση σε αυτή, αλλιώς θα πρέπει να έχεις κάποιο array πχ που το κάθε thread θα χρησιμοποιεί indexed μνήμη από αυτό. Και οι δυο προσεγγίσεις έχουν τα θετικά τους και τα αρνητικά τους, όσων αφορά την ταχύτητα εκτέλεσης και την πολυπλοκότητα.Τέλος το casting είναι πάντα απαραίτητο και μόνο ορισμένες φορές που θέλεις να κάνεις κάποια συγκεκριμένα κόλπα παίζεις με αυτό. Στο υπόλοιπο 99.99% των περιπτώσεων θα πρέπει να είναι όπως το λέει ο nucleus.Το segmentation fault έχει να κάνει με άλλο λάθος στον κώδικά σου και ότι με το casting. Μήπως η μνήμη που δείχνει ο Pointer που περνάς δείχνει στο stack...? Αν συμβαίνει αυτό, τότε είναι λογικό να παίρνεις segmentation fault, γιατί το thread πάει να κάνει προσπέλαση σε mem space που δεν υπάρχει... Link to comment Share on other sites More sharing options...
Thodoris21 Ιούνιος 7, 2012 Author #11 Κοινοποίηση Ιούνιος 7, 2012 Δεν μπορώ να καταλάβω γιατί παίρνω segmentation fault σε αυτό το πρόγραμμα...#include <stdio.h>#include <stdlib.h>#include <time.h>#include <math.h>#include <pthread.h>#define PI 3.14159265int dim;int threads;void *maps(void *id) { int thread_id = *((int*)id); int from = (dim/threads*thread_id); int to = (dim/threads*thread_id)+dim/threads; printf("Map dimensions %dx%d\n",dim,dim);}int main (int argc, char *argv[]) { int i; dim=atoi(argv[1]); threads=atoi(argv[2]); pthread_t tid[threads]; for (i = 0; i < threads; i++) { pthread_create(&tid[i], NULL, &maps,&i); } for (i = 0; i < threads; i++) { pthread_join(tid[i], NULL); } return 0;} Link to comment Share on other sites More sharing options...
Thodoris21 Ιούνιος 7, 2012 Author #12 Κοινοποίηση Ιούνιος 7, 2012 Οκ το εφτιαξα.Το θεμα ειναι οτι εχω ορισεις καποιους πινακες με malloc.Μπορω να τους κανω global? Link to comment Share on other sites More sharing options...
nucleus Ιούνιος 7, 2012 #13 Κοινοποίηση Ιούνιος 7, 2012 Αν τα threads απλώς διαβάζουν τιμές από τους πίνακες και δεν τις αλλάζουν ναι μπορείς να τους κάνεις global.Aν τις αλλάζουν θέλει συγχρονισμό πχ για να μην γράφουν 2 threads στην ίδια θέση. Link to comment Share on other sites More sharing options...
Thodoris21 Ιούνιος 7, 2012 Author #14 Κοινοποίηση Ιούνιος 7, 2012 Οχι τα threads αλλαζουν τιμες των πινακων.Οποτε πρεπει να χρησιμοποιήσω mutexes σωστά?Το θεμα ειναι πως γινεται η global δηλωση των πινακων? Link to comment Share on other sites More sharing options...
nucleus Ιούνιος 7, 2012 #15 Κοινοποίηση Ιούνιος 7, 2012 Όπως κάθε global μεταβλητή.Το θέμα είναι να γίνει σωστα το synchronization με mutexes ή σημαφόρους.Τα thread χρησιμοποιούν τις αλλαγμένες τιμές των πινάκων ή όχι? Link to comment Share on other sites More sharing options...
Thodoris21 Ιούνιος 7, 2012 Author #16 Κοινοποίηση Ιούνιος 7, 2012 Τα threads γεμιζουν τους πινακες με καποιες τιμες και η main() τις τυπωνει.Έκανα μια αλλαγη και μεχρι στιγμης παιζει.#include <stdio.h>#include <stdlib.h>#include <time.h>#include <math.h>#include <pthread.h>#define PI 3.14159265struct timeval StartTime, EndTime;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;int dim;int threads;int** prevkMap;int** nextkMap;float** prevtempMap; float** preveMap;float** nexttempMap; float** nexteMap; void *maps(void *id) { srand(time(NULL)); int thread_id = *((int*)id); int from = (dim/threads*thread_id); int to = (dim/threads*thread_id)+dim/threads; int step,i,j,num; for (step=from; step<to; step++) { pthread_mutex_lock(&mutex); for (i=0; i<dim; i++) { for (j=0; j<dim; j++) { num=rand() % 6; //τυχαίος αριμός μεταξύ 0 και 5 prevkMap[i][j]=num;//πέρασμα τιμής στον πίνακα prevtempMap[i][j]=22; preveMap[i][j]=0; } } pthread_mutex_unlock(&mutex); }}int main (int argc, char *argv[]) { int i,j; dim=atoi(argv[1]); threads=atoi(argv[2]); pthread_t tid[threads]; prevkMap = malloc(dim * sizeof(int*)); nextkMap = malloc(dim * sizeof(int*)); prevtempMap = malloc(dim * sizeof(int*)); preveMap = malloc(dim * sizeof(int*)); nexttempMap = malloc(dim * sizeof(int*)); nexteMap = malloc(dim * sizeof(int*)); for (i = 0; i < dim; i++) { prevkMap[i] = malloc(dim * sizeof(int)); nextkMap[i] = malloc(dim * sizeof(int)); prevtempMap[i] = malloc(dim * sizeof(int)); nexttempMap[i] = malloc(dim * sizeof(int)); preveMap[i] = malloc(dim * sizeof(int)); nexteMap[i] = malloc(dim * sizeof(int)); } gettimeofday(&StartTime, NULL); for (i = 0; i < threads; i++) { pthread_create(&tid[i], NULL, &maps,&i); } for (i = 0; i < threads; i++) { pthread_join(tid[i], NULL); } gettimeofday(&EndTime, NULL); printf("\n"); if (EndTime.tv_usec < StartTime.tv_usec) { int nsec = (StartTime.tv_usec - EndTime.tv_usec) / 1000000 + 1; StartTime.tv_usec -= 1000000 * nsec; StartTime.tv_sec += nsec; } if (EndTime.tv_usec - StartTime.tv_usec > 1000000) { int nsec = (EndTime.tv_usec - StartTime.tv_usec) / 1000000; StartTime.tv_usec += 1000000 * nsec; StartTime.tv_sec -= nsec; } //Εκτύπωση χρόνου σε δευτερόλεπτα printf("\n\nCalculation time: %ld.%.6ld seconds\n", EndTime.tv_sec - StartTime.tv_sec, EndTime.tv_usec - StartTime.tv_usec); free (prevkMap); free (nextkMap); free (prevtempMap); free (nexttempMap); free (preveMap); free (nexteMap); return 0;}Το κομματι του συγχρονισμου ειναι σωστο? Link to comment Share on other sites More sharing options...
nucleus Ιούνιος 7, 2012 #17 Κοινοποίηση Ιούνιος 7, 2012 for (step=from; step<to; step++) { pthread_mutex_lock(&mutex); for (i=0; i<dim; i++) { for (j=0; j<dim; j++) { num=rand() % 6; //τυχαίος αριμός μεταξύ 0 και 5 prevkMap[i][j]=num;//πέρασμα τιμής στον πίνακα prevtempMap[i][j]=22; preveMap[i][j]=0; } } pthread_mutex_unlock(&mutex); }Δεν ξέρω αν πρέπει να μπει και το for στο critical section δηλαδή να γίνει pthread_mutex_lock(&mutex);for (step=from; step<to; step++) { for (i=0; i<dim; i++) { for (j=0; j<dim; j++) { num=rand() % 6; //τυχαίος αριμός μεταξύ 0 και 5 prevkMap[i][j]=num;//πέρασμα τιμής στον πίνακα prevtempMap[i][j]=22; preveMap[i][j]=0; } } } pthread_mutex_unlock(&mutex); Link to comment Share on other sites More sharing options...
Thodoris21 Ιούνιος 7, 2012 Author #18 Κοινοποίηση Ιούνιος 7, 2012 Το πρωτο for οριζει τι κομματι θα παρει καθε thread.Τα επομενα δυο for ειναι για το γεμισμα των πινακων.Εχω την εντυπωση οτι εφοσον το καθε thread παιρνει το δικο του κομματι,δεν εχει νοημα η χρηση των mutexes!Ειναι περιττο και καθυστερει και τον κωδικα νομιζω... Link to comment Share on other sites More sharing options...
nucleus Ιούνιος 7, 2012 #19 Κοινοποίηση Ιούνιος 7, 2012 Αφου δουλεύει δεν το πειράζεις."Τοπικές" μεταβλητές είναι δεν θα πρέπει να έχουν πρόβλημα. Link to comment Share on other sites More sharing options...
Thodoris21 Ιούνιος 7, 2012 Author #20 Κοινοποίηση Ιούνιος 7, 2012 Το θεμα τωρα ειναι οτι οι τιμες των πινακων γραφονται σε αρχεια.Υπαρχει τροπος να ορισω τα file descriptors σαν global μεταβλητες?Για παραδειγμα εχω:FILE * map[24];Θελω να το ορισω σαν global μεταβλητη με χρηση της malloc για να ειναι ορατο και απο την συναρτηση των threads. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.