gpt4 book ai didi

c# - 如何简化 CPU 密集型 For 循环 C#

转载 作者:行者123 更新时间:2023-12-02 08:27:04 27 4
gpt4 key购买 nike

因此,我正在使用 Windows 10 上的 C#、Visual Studio 中的 Unity 制作一个程序生成的世界。我一直无法弄清楚为什么我的 map 无法处理大尺寸,直到我在代码中偶然发现了这组循环。

    for (int index = 0; index < terrainCoords.Count; index++)
{
if (index == terrainCoords.Count)
{
break;
}

touchCount = 0;

for (int posAdd = 0; posAdd < neighbors.Count; posAdd++)
{
newPos = new Vector3Int(terrainCoords[index].x + neighbors[posAdd].Item1, terrainCoords[index].y + neighbors[posAdd].Item2, 0);
touchCount += terrainCoords.Contains(newPos) ? 1 : 0;
}

if (touchCount < 2)
{
terrainCoords.Remove(terrainCoords[index]);
}

}

for (int j = 0; j < caveSmoothness; j++)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (!terrainCoords.Contains(new Vector3Int(x, y, 0)))
{
touchCount = 0;

for (int posAdd = 0; posAdd < neighbors.Count; posAdd++)
{
newPos = new Vector3Int(x + neighbors[posAdd].Item1, y + neighbors[posAdd].Item2, 0);
touchCount += terrainCoords.Contains(newPos) ? 1 : -1;
}

if (touchCount > 1)
{
terrainCoords.Add(new Vector3Int(x, y, 0));
}

}

}

}
}

现在,作为引用,terrainCoords 是我预先生成的用于制作 map 的 Vector3Int 列表,尽管生成的 map 很困惑,因此这些 for 循环通过迭代来清理它们称为“邻居”的元组列表,它是一组数字,当添加到 block 的坐标时,会给出直接接触它们的 block 的所有坐标。第一个循环的目的是删除没有接触足够的固体 block 来构成任何重要结构的自由 float 固体 block 。第二个循环是通过在没有接触足够空 block 的空 block 位置添加 block 来填充可能出现的随机口袋。当caveSmoothness增加时,它还可以填充小的、狭窄的尾部隧道。然而,如果我有一个尺寸为 100*100 且“caveSmoothness”为 2 的 map ,则它必须迭代自身 100,000,000 次,这太多了。这是一个关键的过程,但要避免它导致尴尬的 map 。为了预先生成地形,我使用了 Accidental Noise 的《我的世界》示例并进行了以下设置:

terraintree=
{
{name="ground_gradient", type="gradient", x1=0, x2=0, y1=0, y2=1},

{name="lowland_shape_fractal", type="fractal", fractaltype=anl.BILLOW, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=2, frequency=0.25},
{name="lowland_autocorrect", type="autocorrect", source="lowland_shape_fractal", low=0, high=1},
{name="lowland_scale", type="scaleoffset", source="lowland_autocorrect", scale=0.125, offset=-0.45},
{name="lowland_y_scale", type="scaledomain", source="lowland_scale", scaley=0},
{name="lowland_terrain", type="translatedomain", source="ground_gradient", ty="lowland_y_scale"},

{name="highland_shape_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=4, frequency=2},
{name="highland_autocorrect", type="autocorrect", source="highland_shape_fractal", low=-1, high=1},
{name="highland_scale", type="scaleoffset", source="highland_autocorrect", scale=0.25, offset=0},
{name="highland_y_scale", type="scaledomain", source="highland_scale", scaley=0},
{name="highland_terrain", type="translatedomain", source="ground_gradient", ty="highland_y_scale"},

{name="mountain_shape_fractal", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=8, frequency=1},
{name="mountain_autocorrect", type="autocorrect", source="mountain_shape_fractal", low=-1, high=1},
{name="mountain_scale", type="scaleoffset", source="mountain_autocorrect", scale=0.45, offset=0.15},
{name="mountain_y_scale", type="scaledomain", source="mountain_scale", scaley=0.25},
{name="mountain_terrain", type="translatedomain", source="ground_gradient", ty="mountain_y_scale"},

{name="terrain_type_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=3, frequency=0.125},
{name="terrain_autocorrect", type="autocorrect", source="terrain_type_fractal", low=0, high=1},
{name="terrain_type_y_scale", type="scaledomain", source="terrain_autocorrect", scaley=0},
{name="terrain_type_cache", type="cache", source="terrain_type_y_scale"},
{name="highland_mountain_select", type="select", low="highland_terrain", high="mountain_terrain", control="terrain_type_cache", threshold=0.55, falloff=0.2},
{name="highland_lowland_select", type="select", low="lowland_terrain", high="highland_mountain_select", control="terrain_type_cache", threshold=0.25, falloff=0.15},
{name="highland_lowland_select_cache", type="cache", source="highland_lowland_select"},
{name="ground_select", type="select", low=0, high=1, threshold=0.5, control="highland_lowland_select_cache"},

{name="cave_shape", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=1, frequency=4},
{name="cave_attenuate_bias", type="bias", source="highland_lowland_select_cache", bias=0.45},
{name="cave_shape_attenuate", type="combiner", operation=anl.MULT, source_0="cave_shape", source_1="cave_attenuate_bias"},
{name="cave_perturb_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=6, frequency=3},
{name="cave_perturb_scale", type="scaleoffset", source="cave_perturb_fractal", scale=0.5, offset=0},
{name="cave_perturb", type="translatedomain", source="cave_shape_attenuate", tx="cave_perturb_scale"},
{name="cave_select", type="select", low=1, high=0, control="cave_perturb", threshold=0.48, falloff=0},

{name="ground_cave_multiply", type="combiner", operation=anl.MULT, source_0="cave_select", source_1="ground_select"}
}

尽管我努力在他们的文档中找到降噪/分形平滑度设置并调整设置,但我似乎无法生成与我的 for 循环使用 Ruth-Goldberg 机器相同的结果。如果您可以简化我的 for 循环,找到一种更有效的方法来实现这些结果,或者可以以我没有注意到的方式调整分形设置,我们将非常感谢您的输入。谢谢你! =)

最佳答案

在我看来,这太复杂了。它是一个二维数组,那么为什么不从简单的二维数组开始呢?

Random rnd = new Random(1);
int xSize = 10000;
int ySize = 1000;
byte[,] terrainCoords = new byte[ySize + 2, xSize + 2];

for (int y = 1; y <= ySize; ++y)
{
for (int x = 1; x <= xSize; ++x)
{
if (rnd.Next(100) < 40) //40% fill ratio
{
terrainCoords[y, x] = 1;
}
}
}

var st = new System.Diagnostics.Stopwatch();
st.Start();

for (int y = 1; y <= ySize; ++y)
{
for (int x = 1; x <= xSize; ++x)
{
int touchCount =
terrainCoords[y - 1, x - 1]
+ terrainCoords[y - 1, x]
+ terrainCoords[y - 1, x + 1]
+ terrainCoords[y, x - 1]
+ terrainCoords[y, x + 1]
+ terrainCoords[y + 1, x - 1]
+ terrainCoords[y + 1, x]
+ terrainCoords[y + 1, x + 1];

if (touchCount < 2)
{
terrainCoords[y, x] = 0;
}
}
}

int caveSmoothness = 5;
for (int j = 0; j < caveSmoothness; j++)
{
for (int y = 1; y <= ySize; ++y)
{
for (int x = 1; x <= xSize; ++x)
{
int touchCount =
terrainCoords[y - 1, x - 1]
+ terrainCoords[y - 1, x]
+ terrainCoords[y - 1, x + 1]
+ terrainCoords[y, x - 1]
+ terrainCoords[y, x + 1]
+ terrainCoords[y + 1, x - 1]
+ terrainCoords[y + 1, x]
+ terrainCoords[y + 1, x + 1];

if (touchCount > 4)
{
terrainCoords[y, x] = 1;
}
}
}
}

st.Stop();
Console.WriteLine(st.ElapsedMilliseconds.ToString()); //800ms

我认为这是一个很好的起点。如果您需要更高的性能,可以进一步优化它,但必须在真实数据上完成。

关于c# - 如何简化 CPU 密集型 For 循环 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60609786/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com