【问题标题】:Defining a static array of floats in C++在 C++ 中定义浮点数的静态数组
【发布时间】:2010-11-05 15:45:45
【问题描述】:

我正在使用 C++ 开发行星生成工具,目前我正在尝试生成纹理和高度图。

我为此使用了 3d perlian 噪声函数,因此每次生成纹理或高度图时,我都会计算球体表面上每个顶点的噪声函数值。

这些坐标不会改变。最初我是通过使用this method 将立方体映射到球体来计算这些的。

然后我想好,如果我知道这些值每次都相同,为什么不计算一次并将它们输出到可以定义为静态数组的头文件。

我想创建 512x512 的纹理,这意味着 每个面会生成 260,000+ 个坐标 :(

结果坐标存储在一个数组中:

float textureMapSaved[6][512][512][3] = {etc};

由于立方体有 6 个面,每个面512x512 像素3 个坐标(x、y 和 z)

这有望让我在数组中循环获取我感兴趣的 perlian 噪声函数中的值的坐标。

到目前为止,我只是设法将我的电脑变成了一个令人哭泣的烂摊子。

我的问题是:

有可行的方法吗?

在不创建输出文件的情况下,程序需要大约 15 分钟来计算球体。我实际上无法使用标头进行编译,它使我的计算机崩溃了。

然后我尝试了 256x256,效果稍微好一点,但我的电脑仍然卡壳;我猜这是因为它无法有效地为 4D 数组分配内存。


感谢您的快速回复!

目前我正在做以下事情:

std::vector<std::vector<std::vector<std::vector<float>>>> textureFaces = GenerateSphereCoordinates(TEXTURE_MAP);

std::ofstream myfile;
myfile.open ("spheremapping.h");
myfile << "#ifndef _SPHEREMAP \n#define _SPHEREMAP \n\nfloat textureMapSaved[6][" << textureRes << "][" << textureRes << "][3] = {";
for(int i = 0; i < 6; i++)
{
    myfile << "{";
    for(int j = 0; j < textureRes; j++)
    {
        myfile << "{";
        for(int k = 0; k < textureRes; k++)
        {
            if(k != textureRes - 1)
            {
                myfile << "{ " << textureFaces[i][j][k][0] << ", " << textureFaces[i][j][k][1] << ", " << textureFaces[i][j][k][2] << "}, " ;               
            }
            else
            {
                myfile << "{ " << textureFaces[i][j][k][0] << ", " << textureFaces[i][j][k][1] << ", " << textureFaces[i][j][k][2] << "}" ; 
            }
        }
        if(j != textureRes - 1)
        {
            myfile << "}, \n";
        }
        else
        {
            myfile << "} \n";
        }
    }
    if(i != 5)
    {
        myfile << "}, \n\n";
    }
    else
    {
        myfile << "} \n\n";
    }
}
myfile << "};\n\n#endif";
myfile.close();

如何将其保存为二进制文件并直接读入内存?

【问题讨论】:

  • 这个数组只有大约 16MB 的大小。只要它是静态分配的(使用static 或通过将其放置在命名空间范围内)或动态分配(使用new),并且只要您没有耗尽内存或没有足够大的连续块来容纳它,分配本身不应该成为瓶颈。
  • 如果它使您的计算机崩溃,您可能做错了什么。正如詹姆斯所说,这并不是一个真正的大数组。邮政编码。
  • 那么,你有没有生成头文件呢?还是仅仅计算纹理贴图就需要 15 分钟?如果花费了这么长时间并且您已经生成并包含了标头,我怀疑预处理器没有很好地处理大量的头文件。
  • 那个数组大约有 18M 的内存。 6*512*512*3*sizeof(float) / 1024 /1024 = 18。在堆栈上分配它可能不是一个好主意,因为这样大小的堆栈帧可能存在编译器限制。
  • 所以,你想预先计算一些值,将它们存储在一个数组中,然后使用它们。你的问题在哪里?预计算似乎很慢,编译器崩溃时无法使用存储的值,并且您正在通过循环访问这些数组值......所以,我确定我没有正确理解您的问题。 ..

标签: c++ arrays memory-management static floating-point


【解决方案1】:

您描述的方法是效率和简单性的最佳组合。如果您的编译器无法一次处理整个数组定义,请将问题分解为多个部分。例如:

typedef float CubeFace[512][512][3];
CubeFace face1 = {etc};
...
CubeFace * textureMapSaved[6] = {&face1, &face2, &face3, &face4, &face5, &face6};

作为替代方案,停止尝试将您的定义设为可编译的文本文件,而将其设为二进制文件。您可以通过一次操作将其读入内存,或者将其设为内存映射文件并让操作系统根据需要进行交换。

【讨论】:

  • 确实如此。将数组定义编译成单独的目标文件,并静态或动态链接或extern它。
  • 不,根本不编译数组,最后一段是最好的建议:不要创建源代码,而是将创建的数组写入二进制文件并使用 read( ) 库函数。
  • 我打算照你说的做,保存为二进制。目前我已经尝试了你的第一个建议,我可以编译代码,但是当它构建时,它只会让视觉工作室崩溃。这可能是什么原因造成的?
【解决方案2】:

分别保存您的面孔。另外,我严重怀疑每个像素需要三个坐标;我敢打赌,当与数组坐标中固有的 x、y 值结合使用时,单个标量就足够了。

【讨论】:

    【解决方案3】:

    正如其他人所指出的,数组大小没什么大不了的。还有其他问题,例如您试图将其作为自动变量放入堆栈。

    我要补充一点,在处理这种大小的数据集时,缓存效率在性能中起着重要作用。你的算法应该尝试做两件事: 1) 保持数组读取在时间和内存地址上彼此靠近。这意味着不要在高阶维度上跳来跳去,例如立方体面,直到您处理完低阶维度,例如个别顶点。根据需要重新组织数组维度以帮助实现此目的。 2) 尝试在内存地址方面以可预测的增量模式接触数组。这允许缓存预取器提前主动将数据放入缓存中。

    您也可以将工作分成并行任务,享受各种乐趣。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-13
      • 2011-06-03
      • 1970-01-01
      • 1970-01-01
      • 2011-08-17
      • 1970-01-01
      • 1970-01-01
      • 2012-05-30
      相关资源
      最近更新 更多