Определение статического массива с плавающей точкой в ​​C ++ - PullRequest
2 голосов
/ 05 ноября 2010

Я работаю над инструментом генерации планет в C ++ и в настоящее время пытаюсь сгенерировать текстуры и карты высот.

Я использую для этого функцию трехмерного перлианового шума, поэтому каждый раз, когда я генерируютекстура или карта высот Я вычислю значение функции шума для каждой вершины на поверхности сферы.

Эти координаты не меняются.Первоначально я вычислял их, отображая куб в сферу, используя этот метод .

Затем я хорошо подумал, если я знаю, что эти значения будут одинаковыми каждый раз, почему бы не рассчитать ихи вывести их в файл заголовка, где они могут быть определены как статические массивы.

Я хочу создать текстуры 512x512, это означает, что 260 000 + координаты генерируются для лица : (*

Полученные координаты были сохранены в массиве:

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

Поскольку куб имеет 6 граней , 512x512 пикселей на грань и 3 соординаты (x, y & z) .

Можно надеяться, что это позволит мне затем пройти через массив, получая координату для значения функции перлианского шума, которая меня интересует.

До сих пор мне только удалось превратить мой компьютер в жуткий беспорядок.

Мой вопрос:

Есть ли жизнеспособный способ сделать это?

Без создания выходного файлаПрограмма занимает около 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();

Как сохранить его в виде двоичного файла и прочитать его непосредственно в память?

Ответы [ 3 ]

4 голосов
/ 05 ноября 2010

Метод, который вы описываете, является лучшим сочетанием эффективности и простоты. Если ваш компилятор не может обработать все определение массива сразу, разбейте проблему на части. Например:

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

В качестве альтернативы, прекратите попытки сделать ваше определение компилируемым текстовым файлом и сделайте его двоичным файлом. Вы можете прочитать его в память за одну операцию или сделать из него файл с отображением в памяти и позволить ОС поменять его при необходимости.

0 голосов
/ 05 ноября 2010

Как уже отмечали другие, размер массива не имеет большого значения.Что-то еще идет не так, например, вы пытались поместить это в стек как автоматическую переменную.

Я добавлю, что при работе с наборами данных такого размера эффективность кэша играет большую роль в производительности.Ваш алгоритм должен попытаться сделать две вещи: 1) Держать чтения массивов кластеризованными рядом друг с другом как по времени, так и по адресу памяти.Это означает, что не следует прыгать в измерениях высокого порядка, например гранях куба, пока вы не закончите обработку измерений низкого порядка, например отдельных вершин.Реорганизовать размеры массива по мере необходимости, чтобы помочь достичь этого.2) Попытайтесь коснуться массива в предсказуемом приращении с точки зрения адреса памяти.Это позволяет средствам предварительной выборки в кеше заблаговременно вносить данные в кэш заранее.

Вы можете получить все виды удовольствия, разделив работу на параллельные задачи.

0 голосов
/ 05 ноября 2010

Сохраните ваши лица отдельно.Кроме того, я серьезно сомневаюсь, что вам нужно три координаты на пиксель;Держу пари, что одного скаляра в сочетании с собственными значениями x, y в координатах массива будет достаточно.

...