D 编程语言中的生命游戏
Game of Life in D Programming Language
我正在尝试在 D 中实现生命游戏(这对我来说是新的)。它适用于大小为 100x100、200x200、300x300 的数组,但当我达到 400x400 或更高时,可执行文件停止工作。我该如何解决?这是我的代码:
import std.stdio;
import std.random;
import std.conv:to;
import std.file;
import std.conv:to;
import core.simd;
alias to!(string) toString;
immutable side = 400;
immutable generations = 1000;
alias to!(string) toString;
void main ()
{
//Initialize Game of Life
float[side+2][side+2] big_grid;
float[side][side] cell_grid;
//Input random numbers in the big grid
for ( int i = 1; i < side+1; i++ )
for ( int k = 1; k < side+1; k++ )
{
big_grid[i][k] = uniform(0,2);
}
//Wrap the cells to sides (toroidal) in the big grid
for (int k = 1; k < side+1; k++ )
{
big_grid[side+1][k] = big_grid[1][k];
big_grid[0][k] = big_grid[side][k];
big_grid[k][side + 1] = big_grid[k][1];
big_grid[k][0] = big_grid[k][side];
}
big_grid[side+1][side+1] = big_grid[1][1];
big_grid[0][0] = big_grid[side][side];
big_grid[0][side+1] = big_grid[side][1];
big_grid[side+1][0] = big_grid[1][side];
//Transfer cell information from big grid to cell grid
for ( int i = 1; i < side+1; i++ )
for ( int k = 1; k < side+1; k++ )
{
cell_grid[i-1][k-1] = big_grid[i][k];
}
File file = File("gen0.txt", "w");
for ( int i = 0; i < side; i++ )
{
for ( int k = 0; k < side; k++ )
{
file.write(cell_grid[i][k],",");
}
file.write("\n");
}
file.close();
//Update the state of the cells
for (int d = 1; d < generations; d++ )
{
//Rules of Life
for ( int i = 0; i < side; i++ )
for ( int k = 0; k < side; k++ )
{
if (big_grid[i+1][k+1] == 0 && (big_grid[i][k]+big_grid[i][k+1]+big_grid[i][k+2]+big_grid[i+1][k]+big_grid[i+1][k+1]+big_grid[i+1][k+2]+big_grid[i+2][k]+big_grid[i+2][k+1]+big_grid[i+2][k+2] == 3))
{
cell_grid[i][k] = 1;
}
else if (big_grid[i+1][k+1] == 1 && ((big_grid[i][k]+big_grid[i][k+1]+big_grid[i][k+2]+big_grid[i+1][k]+big_grid[i+1][k+1]+big_grid[i+1][k+2]+big_grid[i+2][k]+big_grid[i+2][k+1]+big_grid[i+2][k+2] == 3) || (big_grid[i][k]+big_grid[i][k+1]+big_grid[i][k+2]+big_grid[i+1][k]+big_grid[i+1][k+1]+big_grid[i+1][k+2]+big_grid[i+2][k]+big_grid[i+2][k+1]+big_grid[i+2][k+2] == 4)))
{
cell_grid[i][k] = 1;
}
else
{
cell_grid[i][k] = 0;
}
}
//Update big grid for next iteration
for ( int i = 1; i < side+1; i++ )
for ( int k = 1; k < side+1; k++ )
{
big_grid[i][k] = cell_grid[i-1][k-1];
}
for (int k = 1; k < side+1; k++ )
{
big_grid[side+1][k] = big_grid[1][k];
big_grid[0][k] = big_grid[side][k];
big_grid[k][side + 1] = big_grid[k][1];
big_grid[k][0] = big_grid[k][side];
}
big_grid[side+1][side+1] = big_grid[1][1];
big_grid[0][0] = big_grid[side][side];
big_grid[0][side+1] = big_grid[side][1];
big_grid[side+1][0] = big_grid[1][side];
file = File("gen"~toString(d)~".txt", "w");
for ( int i = 0; i < side; i++ )
{
for ( int k = 0; k < side; k++ )
{
file.write(cell_grid[i][k],",");
}
file.write("\n");
}
file.close();
}
}
最可能的原因是使用 Windows 的默认堆栈限制,并且至少有两条路径可以解决它。
1。增加堆叠限制。
如果您在 Windows 上编译和 运行 程序,可执行文件通常有自己编译的最大堆栈大小,因此它更像是 OS 特定的而不是特定语言的。
现在,对于编译型编程语言,它们的链接器通常会提供增加最大堆栈大小的选项。例如,如果您使用 dmd(官方 D 编译器)并编译为 32 位目标,命令行将为 dmd -L/STACK:16777216 program.d
以将限制设置为 16 兆字节。 dmd 链接器的选项列表是 here.
2。避免大量使用堆栈。
另一种方法是注意您只需要用于本地纯旧数据变量的堆栈。数组 float[side+2][side+2] big_grid;
是一个 static 数组,这意味着它被分配在声明为 (side+2)
* (side+2)
连续 4 字节 [=14] 的位置=]s.
如果您改为使用 动态 数组 auto big_grid = new float [] [] (side + 2, side + 2);
,这将仅分配 size_t
* 2 个字节(8 或 16,具体取决于位数) 在堆栈上,其余分配(一个动态浮点数组的一维数组和 size+2
一维浮点数组)将发生在垃圾收集堆上。您可以阅读更多关于不同种类的 arrays in D, and even more on using dynamic arrays.
您也可以将数组声明为thread-local:只需将声明从函数范围移动到模块范围。如果你想要一个真正的全局变量,在模块级声明前添加 __gshared
:__gshared float[side+2][side+2] big_grid;
。这样,您仍然可以在不在堆栈上分配的情况下使用静态数组。
我正在尝试在 D 中实现生命游戏(这对我来说是新的)。它适用于大小为 100x100、200x200、300x300 的数组,但当我达到 400x400 或更高时,可执行文件停止工作。我该如何解决?这是我的代码:
import std.stdio;
import std.random;
import std.conv:to;
import std.file;
import std.conv:to;
import core.simd;
alias to!(string) toString;
immutable side = 400;
immutable generations = 1000;
alias to!(string) toString;
void main ()
{
//Initialize Game of Life
float[side+2][side+2] big_grid;
float[side][side] cell_grid;
//Input random numbers in the big grid
for ( int i = 1; i < side+1; i++ )
for ( int k = 1; k < side+1; k++ )
{
big_grid[i][k] = uniform(0,2);
}
//Wrap the cells to sides (toroidal) in the big grid
for (int k = 1; k < side+1; k++ )
{
big_grid[side+1][k] = big_grid[1][k];
big_grid[0][k] = big_grid[side][k];
big_grid[k][side + 1] = big_grid[k][1];
big_grid[k][0] = big_grid[k][side];
}
big_grid[side+1][side+1] = big_grid[1][1];
big_grid[0][0] = big_grid[side][side];
big_grid[0][side+1] = big_grid[side][1];
big_grid[side+1][0] = big_grid[1][side];
//Transfer cell information from big grid to cell grid
for ( int i = 1; i < side+1; i++ )
for ( int k = 1; k < side+1; k++ )
{
cell_grid[i-1][k-1] = big_grid[i][k];
}
File file = File("gen0.txt", "w");
for ( int i = 0; i < side; i++ )
{
for ( int k = 0; k < side; k++ )
{
file.write(cell_grid[i][k],",");
}
file.write("\n");
}
file.close();
//Update the state of the cells
for (int d = 1; d < generations; d++ )
{
//Rules of Life
for ( int i = 0; i < side; i++ )
for ( int k = 0; k < side; k++ )
{
if (big_grid[i+1][k+1] == 0 && (big_grid[i][k]+big_grid[i][k+1]+big_grid[i][k+2]+big_grid[i+1][k]+big_grid[i+1][k+1]+big_grid[i+1][k+2]+big_grid[i+2][k]+big_grid[i+2][k+1]+big_grid[i+2][k+2] == 3))
{
cell_grid[i][k] = 1;
}
else if (big_grid[i+1][k+1] == 1 && ((big_grid[i][k]+big_grid[i][k+1]+big_grid[i][k+2]+big_grid[i+1][k]+big_grid[i+1][k+1]+big_grid[i+1][k+2]+big_grid[i+2][k]+big_grid[i+2][k+1]+big_grid[i+2][k+2] == 3) || (big_grid[i][k]+big_grid[i][k+1]+big_grid[i][k+2]+big_grid[i+1][k]+big_grid[i+1][k+1]+big_grid[i+1][k+2]+big_grid[i+2][k]+big_grid[i+2][k+1]+big_grid[i+2][k+2] == 4)))
{
cell_grid[i][k] = 1;
}
else
{
cell_grid[i][k] = 0;
}
}
//Update big grid for next iteration
for ( int i = 1; i < side+1; i++ )
for ( int k = 1; k < side+1; k++ )
{
big_grid[i][k] = cell_grid[i-1][k-1];
}
for (int k = 1; k < side+1; k++ )
{
big_grid[side+1][k] = big_grid[1][k];
big_grid[0][k] = big_grid[side][k];
big_grid[k][side + 1] = big_grid[k][1];
big_grid[k][0] = big_grid[k][side];
}
big_grid[side+1][side+1] = big_grid[1][1];
big_grid[0][0] = big_grid[side][side];
big_grid[0][side+1] = big_grid[side][1];
big_grid[side+1][0] = big_grid[1][side];
file = File("gen"~toString(d)~".txt", "w");
for ( int i = 0; i < side; i++ )
{
for ( int k = 0; k < side; k++ )
{
file.write(cell_grid[i][k],",");
}
file.write("\n");
}
file.close();
}
}
最可能的原因是使用 Windows 的默认堆栈限制,并且至少有两条路径可以解决它。
1。增加堆叠限制。
如果您在 Windows 上编译和 运行 程序,可执行文件通常有自己编译的最大堆栈大小,因此它更像是 OS 特定的而不是特定语言的。
现在,对于编译型编程语言,它们的链接器通常会提供增加最大堆栈大小的选项。例如,如果您使用 dmd(官方 D 编译器)并编译为 32 位目标,命令行将为 dmd -L/STACK:16777216 program.d
以将限制设置为 16 兆字节。 dmd 链接器的选项列表是 here.
2。避免大量使用堆栈。
另一种方法是注意您只需要用于本地纯旧数据变量的堆栈。数组 float[side+2][side+2] big_grid;
是一个 static 数组,这意味着它被分配在声明为 (side+2)
* (side+2)
连续 4 字节 [=14] 的位置=]s.
如果您改为使用 动态 数组 auto big_grid = new float [] [] (side + 2, side + 2);
,这将仅分配 size_t
* 2 个字节(8 或 16,具体取决于位数) 在堆栈上,其余分配(一个动态浮点数组的一维数组和 size+2
一维浮点数组)将发生在垃圾收集堆上。您可以阅读更多关于不同种类的 arrays in D, and even more on using dynamic arrays.
您也可以将数组声明为thread-local:只需将声明从函数范围移动到模块范围。如果你想要一个真正的全局变量,在模块级声明前添加 __gshared
:__gshared float[side+2][side+2] big_grid;
。这样,您仍然可以在不在堆栈上分配的情况下使用静态数组。