优化代码(康威的生命游戏)
Optimizing code (Conway's Game of Life)
我刚刚制作了康威生命游戏的控制台版本。
它适用于 "small" 网格,例如 100 x 100 像素,但对于更大的网格则非常慢。你能帮我优化一下吗,这样它可以 运行 更快?
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
const int m = 100;
const int n = 100; // size of the grid area
const int num_iter = 1000; // number of iterations to run
int main(){
srand(time(0)); // the initial conditions of the grid should be random
int n_count = 0; // variable for counting the neighbors of a particular point
int iter = 0; // variable for counting the number of iterations done
int grid[m][n] = {0};
int newgrid[m][n] = {0}; // arrays filled with 1's and 0's representing a living or dead cells respectively
HWND myconsole = GetConsoleWindow();
HDC mydc = GetDC(myconsole);
COLORREF WHITE = RGB(255,255,255);
COLORREF BLACK = RGB(0,0,0);
for(long i=0;i<m;i++){ // this for initializes the grid with random 1's
for(long j=0;j<n;j++){
if(rand()%2==0) grid[i][j] = 1;
}
}
while(iter < num_iter){ // while loop controlling the number of iterations to be done
for(long i=0;i<m;i++){
for(long j=0;j<n;j++){ // nested for to count the number of neighbors of each cell
if(i-1>=0) if(grid[i-1][j]==1) n_count++;
if(j-1>=0) if(grid[i][j-1]==1) n_count++;
if(i+1<=n) if(grid[i+1][j]==1) n_count++;
if(j+1<=n) if(grid[i][j+1]==1) n_count++;
if((i-1>=0)&&(j-1>=0)) if(grid[i-1][j-1]==1) n_count++;
if((i-1>=0)&&(j+1<=n)) if(grid[i-1][j+1]==1) n_count++;
if((i+1<=n)&&(j-1>=0)) if(grid[i+1][j-1]==1) n_count++;
if((i+1<=n)&&(j+1<=n)) if(grid[i+1][j+1]==1) n_count++; // all possible 8 neighbors checked and counted by now
if(grid[i][j]==1){ // if the cell is alive and...
if(n_count<2) newgrid[i][j] = 0; // ...it has less than 2 neighbors, then it dies
else if(n_count>3) newgrid[i][j] =0; // ... it has more than 3 neighbors, then it dies
else if((n_count==2)||(n_count==3)) newgrid[i][j] = 1; // ... it has 2 or 3 neighbors, then it lives
}
else if(n_count==3) newgrid[i][j] = 1; // if the cell is dead and it has 3 neighbors, then it lives
n_count = 0;
}
}
for(long i=0;i<m;i++){ // nested for to display a white pixel if the cell is alive, or black if it is dead
for(long j=0;j<n;j++){
grid[i][j] = newgrid[i][j];
if(grid[i][j]==1) SetPixel(mydc,i+50,j+40,WHITE);
else SetPixel(mydc,i+50,j+40,BLACK);
}
}
Sleep(1);
iter++;
}
ReleaseDC(myconsole, mydc);
cin.ignore();
return 0;
}
我认为优化 Conway 的生命游戏本身就是一门科学,我相信 NPE 提供的 link 对此进行了很好的介绍,但如果我可以提出建议,SetPixel
太浪费时间了。
所以,两个优化:
只对那些实际发生变化的像素执行 SetPixel。而不是这个:
grid[i][j] = newgrid[i][j];
if(grid[i][j]==1) SetPixel(mydc,i+50,j+40,WHITE);
else SetPixel(mydc,i+50,j+40,BLACK);
这样做:
if( grid[i][j] != newgrid[i][j] )
{
grid[i][j] = newgrid[i][j];
if(grid[i][j]==1) SetPixel(mydc,i+50,j+40,WHITE);
else SetPixel(mydc,i+50,j+40,BLACK);
}
完全停止使用 SetPixel;尝试获取位图,锁定它以访问其内存缓冲区,直接操作内存缓冲区的字节以将颜色值存储在其中,然后最后将其解锁并将其 blit 到设备上下文。这听起来可能需要大量工作,但请相信我,与对 SetPixel 的无数次调用相比,它实际上代表了 巨大 的性能改进。
我刚刚制作了康威生命游戏的控制台版本。 它适用于 "small" 网格,例如 100 x 100 像素,但对于更大的网格则非常慢。你能帮我优化一下吗,这样它可以 运行 更快?
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
const int m = 100;
const int n = 100; // size of the grid area
const int num_iter = 1000; // number of iterations to run
int main(){
srand(time(0)); // the initial conditions of the grid should be random
int n_count = 0; // variable for counting the neighbors of a particular point
int iter = 0; // variable for counting the number of iterations done
int grid[m][n] = {0};
int newgrid[m][n] = {0}; // arrays filled with 1's and 0's representing a living or dead cells respectively
HWND myconsole = GetConsoleWindow();
HDC mydc = GetDC(myconsole);
COLORREF WHITE = RGB(255,255,255);
COLORREF BLACK = RGB(0,0,0);
for(long i=0;i<m;i++){ // this for initializes the grid with random 1's
for(long j=0;j<n;j++){
if(rand()%2==0) grid[i][j] = 1;
}
}
while(iter < num_iter){ // while loop controlling the number of iterations to be done
for(long i=0;i<m;i++){
for(long j=0;j<n;j++){ // nested for to count the number of neighbors of each cell
if(i-1>=0) if(grid[i-1][j]==1) n_count++;
if(j-1>=0) if(grid[i][j-1]==1) n_count++;
if(i+1<=n) if(grid[i+1][j]==1) n_count++;
if(j+1<=n) if(grid[i][j+1]==1) n_count++;
if((i-1>=0)&&(j-1>=0)) if(grid[i-1][j-1]==1) n_count++;
if((i-1>=0)&&(j+1<=n)) if(grid[i-1][j+1]==1) n_count++;
if((i+1<=n)&&(j-1>=0)) if(grid[i+1][j-1]==1) n_count++;
if((i+1<=n)&&(j+1<=n)) if(grid[i+1][j+1]==1) n_count++; // all possible 8 neighbors checked and counted by now
if(grid[i][j]==1){ // if the cell is alive and...
if(n_count<2) newgrid[i][j] = 0; // ...it has less than 2 neighbors, then it dies
else if(n_count>3) newgrid[i][j] =0; // ... it has more than 3 neighbors, then it dies
else if((n_count==2)||(n_count==3)) newgrid[i][j] = 1; // ... it has 2 or 3 neighbors, then it lives
}
else if(n_count==3) newgrid[i][j] = 1; // if the cell is dead and it has 3 neighbors, then it lives
n_count = 0;
}
}
for(long i=0;i<m;i++){ // nested for to display a white pixel if the cell is alive, or black if it is dead
for(long j=0;j<n;j++){
grid[i][j] = newgrid[i][j];
if(grid[i][j]==1) SetPixel(mydc,i+50,j+40,WHITE);
else SetPixel(mydc,i+50,j+40,BLACK);
}
}
Sleep(1);
iter++;
}
ReleaseDC(myconsole, mydc);
cin.ignore();
return 0;
}
我认为优化 Conway 的生命游戏本身就是一门科学,我相信 NPE 提供的 link 对此进行了很好的介绍,但如果我可以提出建议,SetPixel
太浪费时间了。
所以,两个优化:
只对那些实际发生变化的像素执行 SetPixel。而不是这个:
grid[i][j] = newgrid[i][j]; if(grid[i][j]==1) SetPixel(mydc,i+50,j+40,WHITE); else SetPixel(mydc,i+50,j+40,BLACK);
这样做:
if( grid[i][j] != newgrid[i][j] ) { grid[i][j] = newgrid[i][j]; if(grid[i][j]==1) SetPixel(mydc,i+50,j+40,WHITE); else SetPixel(mydc,i+50,j+40,BLACK); }
完全停止使用 SetPixel;尝试获取位图,锁定它以访问其内存缓冲区,直接操作内存缓冲区的字节以将颜色值存储在其中,然后最后将其解锁并将其 blit 到设备上下文。这听起来可能需要大量工作,但请相信我,与对 SetPixel 的无数次调用相比,它实际上代表了 巨大 的性能改进。