C++ OpenMP与使用SFML的生命游戏可视化
你好,我正在尝试比较《生活游戏》的串行和并行版本的速度。 我使用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
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;tgamefieldParallel和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))) {
...
}