static void generate_tsp_jobs (struct tsp_queue *q, int hops, int len, tsp_path_t path, long long int *cuts, tsp_path_t sol, int *sol_len, int depth) { if (len >= minimum) { (*cuts)++ ; return; } if (hops == depth) { /* On enregistre du travail à faire plus tard... */ add_job (q, path, hops, len); } else { int me = path [hops - 1]; for (int i = 0; i < nb_towns; i++) { if (!present (i, hops, path)) { path[hops] = i; int dist = distance[me][i]; generate_tsp_jobs (q, hops + 1, len + dist, path, cuts, sol, sol_len, depth); } } } }
int main (int argc, char **argv) { unsigned long long perf; tsp_path_t path; struct tsp_queue q; struct timespec t1, t2; /* lire les arguments */ int opt; while ((opt = getopt(argc, argv, "s")) != -1) { switch (opt) { case 's': affiche_sol = true; break; default: usage(argv[0]); break; } } if (optind != argc-3) usage(argv[0]); nb_towns = atoi(argv[optind]); myseed = atol(argv[optind+1]); nb_threads = atoi(argv[optind+2]); assert(nb_towns > 0); assert(nb_threads > 0); minimum = INT_MAX; /* generer la carte et la matrice de distance */ fprintf (stderr, "ncities = %3d\n", nb_towns); genmap (); init_queue (&q); clock_gettime (CLOCK_REALTIME, &t1); /* on vide le chemin 'path' : on met des -1 dans toutes les cases */ memset (path, -1, MAX_TOWNS * sizeof (int)); /* on définit la première ville comme étant 0 */ path[0] = 0; /* On met des travaux dans la file d'attente q */ generate_tsp_jobs (&q, 1, 0, path, &cuts, sol, & sol_len, 3); no_more_jobs (&q); /* on vide le chemin 'solution' : on met des -1 dans toutes les cases */ /* puis on définit la première ville comme étant 0 */ tsp_path_t solution; memset (solution, -1, MAX_TOWNS * sizeof (int)); solution[0] = 0; /* allocation du tableau d'informations sur les threads */ tab_threads = malloc(nb_threads*sizeof(Cell)); memset(tab_threads, 0, nb_threads*sizeof(int)); /* initialisation du mutex*/ pthread_mutex_init(&mutex, NULL); int i; /* on place tous les threads dans l'état 'non-occupé' */ for(i=0; i<nb_threads; i++){ tab_threads[i].occupe = 0; } /* Tant que la file de jobs n'est pas vide on sort un job et on l'execute avec tsp */ while (!empty_queue (&q)) { int hops = 0, len = 0; /* on récupère un job dans la file d'atente des jobs */ get_job (&q, solution, &hops, &len); i = 0; /* on boucle tant qu'on n'a pas trouvé de thread pour effectuer le job */ while (1){ /* si le thread i n'est pas occupé alors on va l'utiliser pour effectuer le job */ if(!tab_threads[i].occupe){ /* on place le thread i en statut 'occupé' */ tab_threads[i].occupe = 1; /* on crée une structure arguments qui va recevoir les arguments de tsp */ struct arg_struct arguments; arguments.hops = hops; arguments.len = len; memcpy(arguments.path, solution, nb_towns * sizeof (int)); /* tsp est récursive et on a besoin de savoir quand le thread a terminé le job afin de le mettre en 'non-occupé' */ /* On introduit donc un entier qui est 1 si le tsp appelé est celui du père et 0 si c'est dans les fils */ arguments.pere = 1; /* lancement du thread sur tsp avec les bons arguments*/ pthread_create (&tab_threads[i].thread, NULL, tsp, (void*)&arguments); break; } /* sinon on va regarder si le suivant%nb_threads est occupé */ i = (i+1)%nb_threads; } } i = 0; /* on attend la fin de tous les threads avant de continuer */ while(1){ pthread_join(tab_threads[i].thread, NULL); i++; if (i == nb_threads) break; } clock_gettime (CLOCK_REALTIME, &t2); if (affiche_sol) print_solution_svg (sol, sol_len); perf = TIME_DIFF (t1,t2); printf("<!-- # = %d seed = %ld len = %d threads = %d time = %lld.%03lld ms ( %lld coupures ) -->\n", nb_towns, myseed, sol_len, nb_threads, perf/1000000ll, perf%1000000ll, cuts); return 0 ; }
int main (int argc, char **argv) { unsigned long long perf; tsp_path_t path; uint64_t vpres=0; struct timespec t1, t2; pthread_mutex_init(&q_mutex, NULL); pthread_mutex_init(&sol_mutex, NULL); pthread_mutex_init(&minimum_mutex, NULL); pthread_mutex_init(&cuts_mutex, NULL); /* lire les arguments */ int opt; while ((opt = getopt(argc, argv, "spq")) != -1) { switch (opt) { case 's': affiche_sol = true; break; case 'p': affiche_progress = true; break; case 'q': quiet = true; break; default: usage(argv[0]); break; } } if (optind != argc-3) usage(argv[0]); nb_towns = atoi(argv[optind]); myseed = atol(argv[optind+1]); nb_threads = atoi(argv[optind+2]); assert(nb_towns > 0); assert(nb_threads > 0); minimum = INT_MAX; /* generer la carte et la matrice de distance */ if (! quiet) fprintf (stderr, "ncities = %3d\n", nb_towns); genmap (); init_queue (&q); clock_gettime (CLOCK_REALTIME, &t1); memset (path, -1, MAX_TOWNS * sizeof (int)); path[0] = 0; vpres=1; /* mettre les travaux dans la file d'attente */ generate_tsp_jobs (&q, 1, 0, vpres, path, &cuts, sol, & sol_len, 3); no_more_jobs (&q); /* generate other threads */ pthread_t *tids = malloc((nb_threads-1)*sizeof(pthread_t)); for(int i = 0; i < nb_threads-1; i++){ pthread_create(&(tids[i]), NULL, main_tsp, NULL); } main_tsp(NULL); // /* calculer chacun des travaux */ // long long int myCuts = 0; // tsp_path_t solution; // memset (solution, -1, MAX_TOWNS * sizeof (int)); // solution[0] = 0; // while (!empty_queue (&q, &q_mutex)) { // int hops = 0, len = 0; // get_job (&q, solution, &hops, &len, &vpres, &q_mutex); // // // le noeud est moins bon que la solution courante // if (minimum < INT_MAX // && (nb_towns - hops) > 10 // && ( (lower_bound_using_hk(solution, hops, len, vpres)) >= minimum // || (lower_bound_using_lp(solution, hops, len, vpres)) >= minimum) // ) // // continue; // // tsp (hops, len, vpres, solution, &myCuts, sol, &sol_len); // } // // /* update cuts */ // pthread_mutex_lock(&cuts_mutex); // cuts += myCuts; // pthread_mutex_unlock(&cuts_mutex); // clock_gettime (CLOCK_REALTIME, &t2); // perf = TIME_DIFF (t1,t2); // printf("Main thread finished after %lld.%03lld ms\n\n", perf/1000000ll, perf%1000000ll); /* wait for other threads */ for(int i = 0; i < nb_threads-1; i++){ pthread_join(tids[i], NULL); } clock_gettime (CLOCK_REALTIME, &t2); if (affiche_sol) //print_solution_svg (sol, sol_len); print_solution_svg_to_file (sol, sol_len); perf = TIME_DIFF (t1,t2); printf("<!-- # = %d seed = %ld len = %d threads = %d time = %lld.%03lld ms ( %lld coupures ) -->\n", nb_towns, myseed, sol_len, nb_threads, perf/1000000ll, perf%1000000ll, cuts); pthread_mutex_destroy(&q_mutex); pthread_mutex_destroy(&sol_mutex); pthread_mutex_destroy(&minimum_mutex); pthread_mutex_destroy(&cuts_mutex); return 0 ; }
/* Main */ int main (int argc, char **argv) { unsigned long long perf; tsp_path_t path; tsp_path_t sol; int sol_len; long long int cuts = 0; struct tsp_queue q; struct timespec t1, t2; /* lire les arguments */ int opt; while ((opt = getopt(argc, argv, "s")) != -1) { switch (opt) { case 's': affiche_sol = true; break; default: usage(argv[0]); break; } } if (optind != argc-3) usage(argv[0]); nb_towns = atoi(argv[optind]); myseed = atol(argv[optind+1]); nb_threads = atoi(argv[optind+2]); assert(nb_towns > 0); assert(nb_threads > 0); minimum = INT_MAX; /* generer la carte et la matrice de distance */ fprintf (stderr, "ncities = %3d\n", nb_towns); genmap (); init_queue (&q); clock_gettime (CLOCK_REALTIME, &t1); memset (path, -1, MAX_TOWNS * sizeof (int)); path[0] = 0; /* mettre les travaux dans la file d'attente */ generate_tsp_jobs (&q, 1, 0, path, &cuts, sol, & sol_len, 3); no_more_jobs (&q); /* calculer chacun des travaux */ tsp_path_t solution; memset (solution, -1, MAX_TOWNS * sizeof (int)); solution[0] = 0; ThreadCell* list = NULL; ThreadCell* cur = NULL; for (int i = 0; i < nb_threads; i++) { ThreadCell* cell = (ThreadCell*) malloc(sizeof(ThreadCell)); cell->next = NULL; WorkerArgs* args = (WorkerArgs*) malloc(sizeof(WorkerArgs)); args->q = &q; memcpy(args->solution, solution, sizeof(tsp_path_t)); args->cuts = &cuts; memcpy(args->sol, sol, sizeof(tsp_path_t)); args->sol_len = &sol_len; pthread_create(&(cell->tid), NULL, tsp_worker, (void*) args); if (!list) { list = cell; cur = list; } else { cur->next = cell; cur = cur->next; } } void * status; while (list != NULL) { pthread_join(list->tid, &status); if (status == PTHREAD_CANCELED) { printf("Thread cancelled"); exit(EXIT_FAILURE); } ThreadCell* tmp = list; list = list->next; free(tmp); } clock_gettime (CLOCK_REALTIME, &t2); if (affiche_sol) print_solution_svg (sol, sol_len); perf = TIME_DIFF (t1,t2); printf("<!-- # = %d seed = %ld len = %d threads = %d time = %lld.%03lld ms ( %lld coupures ) -->\n", nb_towns, myseed, sol_len, nb_threads, perf/1000000ll, perf%1000000ll, cuts); freemap(); return 0 ; }
int main (int argc, char **argv) { unsigned long long perf; tsp_path_t path; tsp_path_t sol; int sol_len; long long int cuts = 0; struct tsp_queue q; struct timespec t1, t2; /* lire les arguments */ int opt; while ((opt = getopt(argc, argv, "s")) != -1) { switch (opt) { case 's': affiche_sol = true; break; default: usage(argv[0]); break; } } if (optind != argc-3) usage(argv[0]); nb_towns = atoi(argv[optind]); myseed = atol(argv[optind+1]); nb_threads = atoi(argv[optind+2]); assert(nb_towns > 0); assert(nb_threads > 0); minimum = INT_MAX; /* generer la carte et la matrice de distance */ fprintf (stderr, "ncities = %3d\n", nb_towns); genmap (); init_queue (&q); clock_gettime (CLOCK_REALTIME, &t1); memset (path, -1, MAX_TOWNS * sizeof (int)); path[0] = 0; /* mettre les travaux dans la file d'attente */ generate_tsp_jobs (&q, 1, 0, path, &cuts, sol, & sol_len, 3); no_more_jobs (&q); /* calculer chacun des travaux */ tsp_path_t solution; memset (solution, -1, MAX_TOWNS * sizeof (int)); solution[0] = 0; while (!empty_queue (&q)) { int hops = 0, len = 0; get_job (&q, solution, &hops, &len); tsp (hops, len, solution, &cuts, sol, &sol_len); } clock_gettime (CLOCK_REALTIME, &t2); if (affiche_sol) print_solution_svg (sol, sol_len); perf = TIME_DIFF (t1,t2); printf("<!-- # = %d seed = %ld len = %d threads = %d time = %lld.%03lld ms ( %lld coupures ) -->\n", nb_towns, myseed, sol_len, nb_threads, perf/1000000ll, perf%1000000ll, cuts); return 0 ; }