Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <time.h>
- #include <omp.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <vector>
- #define ANSI_COLOR_RESET "\x1b[0m"
- #define ANSI_COLOR_DEAD "\x1b[34m"
- #define ANSI_COLOR_POPULATION_1 "\x1b[31m"
- #define ANSI_COLOR_POPULATION_2 "\x1b[32m"
- // na pełny ekran 1440x900 optymalny rozmiar to około 54x175
- const int X = 54; // wiersze
- const int Y = 175; // kolumny
- const int CELL_COUNT = X * Y; //liczba komorek
- const int ITERATION_COUNT = 200; //liczba iteracji - czas trwania symulacji
- const double TIME_INTERVAL = 0.75f; // in seconds (co ile ma iść następna iteracja)
- const int DEAD_FIELD = 0, FIRST_POPULATION = 1, SECOND_POPULATION = 2;
- char tab[2][X + 2][Y + 2];
- void clearTable(char tab[2][X + 2][Y + 2], int layer);
- void initTable(char tab[2][X + 2][Y + 2], int layer, int percentage, int populationId);
- char setCellState(const char tab[2][X + 2][Y + 2], int row, int col, int whichLayer);
- void printTable(const char tab[2][X + 2][Y + 2], int whichLayer);
- void clear_screen();
- int t1_currentRow, t2_currentRow;
- bool threadsMet = false; // Informuje czy wątki się spotkały (są w tym samym wierszu tablicy) w danej iteracji
- int main()
- {
- omp_set_num_threads(2); //omp - ustawienie liczby wątkow
- srand((unsigned int)time(NULL));
- initTable(tab, 0, 50, FIRST_POPULATION);
- initTable(tab, 0, 50, SECOND_POPULATION);
- printf("Zmaksymalizuj ekran i nacisnij enter...");
- getchar();
- printTable(tab, 0);
- double programTimestart = omp_get_wtime();
- double start = 0;
- // #################################### MAIN LOOP ######################################
- //zagniezdzone rownoleglosci (rekurencyjne wywolywanie powoduje zwiekszenie sie watkow)
- //np. 4 razy wywolane z ustawionymi dwoma watkami na samym poczatku - 2^4=16
- omp_set_nested(true);
- //za pomoca omp_lock_t tworzymy zmienna do sekcji krytycznych (lock'ow)
- omp_lock_t lock;
- omp_init_lock(&lock);
- for (int t = 0; t < ITERATION_COUNT; t++) {
- clear_screen();
- start = omp_get_wtime();
- while (true) // odczekaj TIME_INTERVAL
- if (omp_get_wtime() - start > TIME_INTERVAL) break;
- //rozpoczecie rownleglosci.
- #pragma omp parallel
- {
- //przypisanie niezaleznych od siebie blokow kodu.
- #pragma omp sections
- {
- // Jeden wątek sprawdza komórki od góry...
- #pragma omp section
- {
- for (int i = 1; i <= X; i++) {
- t1_currentRow = i;
- for (int j = 1; j <= Y; j++)
- tab[(t + 1) % 2][i][j] = setCellState(tab, i, j, t % 2);
- //sekcja krytyczna
- omp_set_lock(&lock);
- //sprawdza czy watki maja takie same zmienne t1.... i t2...
- #pragma omp flush(t1_currentRow, t2_currentRow)
- if (threadsMet) {
- omp_unset_lock(&lock);
- //koniec sekcji krytycznej
- break;
- }
- // Sprawdź czy wątki są na tym samym wierszu
- threadsMet = (t2_currentRow - t1_currentRow < 1 && t2_currentRow - t1_currentRow >= 0);
- omp_unset_lock(&lock);
- } // for (int i = 1; i <= X; i++)
- } // #pragma omp section
- // ...a drugi od dołu
- #pragma omp section
- {
- for (int k = X; k >= 1; k--) {
- t2_currentRow = k;
- for (int l = Y; l >= 1; l--)
- tab[(t + 1) % 2][k][l] = setCellState(tab, k, l, t % 2);
- omp_set_lock(&lock);
- #pragma omp flush(t1_currentRow, t2_currentRow)
- if (threadsMet) {
- omp_unset_lock(&lock);
- break;
- }
- // sprawdz czy wątki są na tym samym wierszu
- if ((t2_currentRow - t1_currentRow) == 0)
- threadsMet = true;
- omp_unset_lock(&lock);
- } // for (int k = X ; k >= 1; k--)
- } // #pragma omp section
- } // #pragra omp sections
- } // #pragma omp parallel
- threadsMet = false;
- t2_currentRow = X;
- t1_currentRow = 1;
- printTable(tab, (t + 1) % 2);
- } // for (int t = 0; t < ITERATION_COUNT; t++)
- // #################################### MAIN LOOP ###################################### END
- double programTimestop = omp_get_wtime();
- printf("Elapsed time: %f\n", programTimestop - programTimestart);
- omp_destroy_lock(&lock);
- return EXIT_SUCCESS;
- }
- void clear_screen() {
- printf("\033[H\033[J");
- }
- void initTable(char tab[2][X + 2][Y + 2], int layer, int percentage, int population)
- {
- for (int i = 1; i < X; i++)
- for (int j = 1; j < Y; j++)
- if ((rand() % percentage) == (percentage-1)) // zamiast 9 może być dowolona liczba od 0 do percentage - 1
- tab[layer][i][j] = population;
- }
- char setCellState(const char tab[2][X + 2][Y + 2], int row, int col, int layer)
- {
- std::vector<int> populationCount(SECOND_POPULATION + 1, 0);
- populationCount[tab[layer][row - 1][col]]++;
- populationCount[tab[layer][row - 1][col + 1]]++;
- populationCount[tab[layer][row][col - 1]]++;
- populationCount[tab[layer][row][col + 1]]++;
- populationCount[tab[layer][row + 1][col - 1]]++;
- populationCount[tab[layer][row + 1][col]]++;
- populationCount[tab[layer][row + 1][col + 1]]++;
- populationCount[tab[layer][row - 1][col - 1]]++;
- bool population1Lives = (populationCount[FIRST_POPULATION] == 2 || populationCount[FIRST_POPULATION] == 3);
- bool population2Lives = (populationCount[SECOND_POPULATION] == 2 || populationCount[SECOND_POPULATION] == 3);
- int randomFactor = rand() % 2 + 1;
- return (!population1Lives && !population2Lives) ? DEAD_FIELD :
- (population1Lives && !population2Lives) ? FIRST_POPULATION :
- (!population1Lives && population2Lives) ? SECOND_POPULATION :
- (randomFactor == 0) ? FIRST_POPULATION : SECOND_POPULATION;
- }
- void printTable(const char tab[2][X + 2][Y + 2], int layer)
- {
- for (int i = 1; i <= X; i++) {
- for (int j = 1; j <= Y; j++) {
- switch (tab[layer][i][j])
- {
- case FIRST_POPULATION:
- printf(ANSI_COLOR_POPULATION_1 "x" ANSI_COLOR_RESET);
- break;
- case SECOND_POPULATION:
- printf(ANSI_COLOR_POPULATION_2 "x" ANSI_COLOR_RESET);
- break;
- default:
- printf(ANSI_COLOR_DEAD "o" ANSI_COLOR_RESET);
- break;
- }
- }
- printf("\n");
- }
- }
- void clearTable(char tab[2][X + 2][Y + 2], int layer)
- {
- for (int i = 1; i < X; i++)
- for (int j = 1; j < Y; j++)
- tab[layer][i][j] = DEAD_FIELD;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement