C++ OpenMP与使用SFML的生命游戏可视化

C++ OpenMP与使用SFML的生命游戏可视化,c++,c,parallel-processing,openmp,conways-game-of-life,C++,C,Parallel Processing,Openmp,Conways Game Of Life,你好,我正在尝试比较《生活游戏》的串行和并行版本的速度。 我使用SFML库来形象化生活中的游戏,就像这样。 串行逻辑如下所示 for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int neighbor = 0; // check 8 cells around. // 1 2 3

你好,我正在尝试比较《生活游戏》的串行和并行版本的速度。 我使用SFML库来形象化生活中的游戏,就像这样。 串行逻辑如下所示

for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int neighbor = 0;

                // check 8 cells around.
                // 1 2 3  -1
                // 4   5  0
                // 6 7 8  +1

                // (1)
                if (gamefieldSerial.isAvailableCell(UP(i), LEFT(j))) {
                    if(gamefieldSerial[UP(i)][LEFT(j)] == LIVE) neighbor++;
                }
                // (2)
                if (gamefieldSerial.isAvailableCell(UP(i), j)) {
                    if (gamefieldSerial[UP(i)][j] == LIVE)      neighbor++;
                }
                // (3)
                if (gamefieldSerial.isAvailableCell(UP(i), RIGHT(j))) {
                    if (gamefieldSerial[UP(i)][RIGHT(j)] == LIVE)   neighbor++;
                }
                // (4)
                if (gamefieldSerial.isAvailableCell(i, LEFT(j))) {
                    if (gamefieldSerial[i][LEFT(j)] == LIVE)        neighbor++;
                }
                // (5)
                if (gamefieldSerial.isAvailableCell(i, RIGHT(j))) {
                    if (gamefieldSerial[i][RIGHT(j)] == LIVE)       neighbor++;
                }
                // (6)
                if (gamefieldSerial.isAvailableCell(DOWN(i), LEFT(j))) {
                    if (gamefieldSerial[DOWN(i)][LEFT(j)] == LIVE)  neighbor++;
                }
                // (7)
                if (gamefieldSerial.isAvailableCell(DOWN(i), j)) {
                    if (gamefieldSerial[DOWN(i)][j] == LIVE)        neighbor++;
                }
                // (8)
                if (gamefieldSerial.isAvailableCell(DOWN(i), RIGHT(j))) {
                    if (gamefieldSerial[DOWN(i)][RIGHT(j)] == LIVE) neighbor++;
                }

                // -- Rule of Game of Life
                // Cell borns when exactly 3 neighbor is LIVE
                // Cell remains alive when 2 or 3 neighbor is LIVE
                // Cell with more than 3 neighbor dies with overpopulation
                // Cell with less than 2 neighbor dies with underpopulation
                if (gamefieldSerial[i][j] == DEAD) {
                    if (neighbor == 3) {
                        gamefieldSerial[i][j] = LIVE;
                    }
                }
                else if (gamefieldSerial[i][j] == LIVE) {
                    if (neighbor < 2 || neighbor > 3) {
                        gamefieldSerial[i][j] = DEAD;
                    }
                }
            }
for(int i=0;i3){
gamefieldSerial[i][j]=死亡;
}
}
}
在100代768*256个细胞上需要3940毫秒。 但在并行版本中,我实现如下所示

#pragma omp parallel for num_threads(4)
        for (int t = 0; t < width * height; t++) {
            int i = t / width;
            int j = t % width;
            int neighbor = 0;

            // check 8 cells around.
            // 1 2 3  -1
            // 4   5  0
            // 6 7 8  +1

            // (1)
            if (gamefieldParallel.isAvailableCell(UP(i), LEFT(j))) {
                if (gamefieldParallel[UP(i)][LEFT(j)] == LIVE) neighbor++;
            }
            // (2)
            if (gamefieldParallel.isAvailableCell(UP(i), j)) {
                if (gamefieldParallel[UP(i)][j] == LIVE)      neighbor++;
            }
            // (3)
            if (gamefieldParallel.isAvailableCell(UP(i), RIGHT(j))) {
                if (gamefieldParallel[UP(i)][RIGHT(j)] == LIVE)   neighbor++;
            }
            // (4)
            if (gamefieldParallel.isAvailableCell(i, LEFT(j))) {
                if (gamefieldParallel[i][LEFT(j)] == LIVE)        neighbor++;
            }
            // (5)
            if (gamefieldParallel.isAvailableCell(i, RIGHT(j))) {
                if (gamefieldParallel[i][RIGHT(j)] == LIVE)       neighbor++;
            }
            // (6)
            if (gamefieldParallel.isAvailableCell(DOWN(i), LEFT(j))) {
                if (gamefieldParallel[DOWN(i)][LEFT(j)] == LIVE)  neighbor++;
            }
            // (7)
            if (gamefieldParallel.isAvailableCell(DOWN(i), j)) {
                if (gamefieldParallel[DOWN(i)][j] == LIVE)        neighbor++;
            }
            // (8)
            if (gamefieldParallel.isAvailableCell(DOWN(i), RIGHT(j))) {
                if (gamefieldParallel[DOWN(i)][RIGHT(j)] == LIVE) neighbor++;
            }

            // -- Rule of Game of Life
            // Cell borns when exactly 3 neighbor is LIVE
            // Cell remains alive when 2 or 3 neighbor is LIVE
            // Cell with more than 3 neighbor dies with overpopulation
            // Cell with less than 2 neighbor dies with underpopulation
            if (gamefieldParallel[i][j] == DEAD) {
                if (neighbor == 3) {
                    gamefieldParallel[i][j] = LIVE;
                }
            }
            else if (gamefieldParallel[i][j] == LIVE) {
                if (neighbor < 2 || neighbor > 3) {
                    gamefieldParallel[i][j] = DEAD;
                }
            }
        }
用于num_线程的pragma omp并行(4) 对于(int t=0;t3){ gamefieldParallel[i][j]=死亡; } } } 在同一环境下,耗时5746毫秒。 我认为在for循环中应用openMP的“for”指令可以提高性能,但事实并非如此。 我应该用另一种方法吗

=============
gamefieldParallel和gamefieldSerial都是GameField类的实例,该类为单元格动态分配了int**field变量。我使用运算符重载来访问它,就像访问二维数组一样。(很抱歉英语不好!)

在串行版本和并行版本中,您都在迭代更新游戏场。这是两个版本的错误。假设您计算
游戏场[0][0]
的新状态,然后进行更新。现在,作为cal的一部分,转到
游戏场[0][1]
#pragma omp parallel
{
  // Generations loop (1)
  for (int gen = 0; gen < NUM_GENERATIONS; gen++) {

    // Compute the new current generation (2)
    #pragma omp for
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
        // Count the number of live neighbours of current[i][j] (3)
        int neighbours = count_neighbours(current, i, j);
        
        // Update the state of the current cell (4)
        if (current[i][j] == DEAD && neighbours == 3)
          next[i][j] = LIVE;
        else if (current[i][j] == LIVE)
          next[i][j] = (neighbours < 2 || neighbours > 3) ? DEAD : LIVE;
      }
    }

    // The following block runs in the master thread (5)
    #pragma omp master
    {
      // Swap the current and next arrays
      std::swap(current, next);

      // Display the board state (if necessary)
      display(current);
    }

    // Synchronise the threads before the next iteration (6)
    #pragma omp barrier
  }
}
    // The following block runs in the master thread (5)
    #pragma omp master
    {
      // Swap the current and next arrays
      std::swap(current, next);

      // Display the board state (if necessary)
      display(current);
    }

    // Synchronise the threads before the next iteration (6)
    #pragma omp barrier
    #pragma omp single
    std::swap(current, next);
if (gamefield.isAvailableCell(UP(i), LEFT(j))) {
   ...
}