Постоянное время построения / реинтерпретации векторов совместимых данных? - PullRequest
1 голос
/ 24 апреля 2020

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

Например, в графике вы можете иметь вектор с плавающей точкой std и стандартный вектор glm vec3s.

Оба они по сути представляют собой непрерывный массив чисел с плавающей запятой, где данные интерпретируются следующим образом: {{x,y,z}, {x,y,z} ...}

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

vector<vec3> v1;
float* ptr = (float*) v1.data;

Вышеприведенное позволит вам рассматривать этот указатель как указатель на массив с плавающей точкой (при условии, что вы используете правильную индексацию). И это можно сделать как постоянную операцию.

Однако это не переносит владение данными и может привести к зависанию указателей, например, если вы сделали:

float* GetPtr()
{
    vector<vec3> v1;
    return (float*) v1.data;
}

Выше явно собирается вызвать проблемы.

Чтобы получить постоянное время преобразования типов, я использую метод, который злоупотребляет неопределенным поведением, чтобы заставить вещи работать:

vector<float> GetVerts()
{
    vector<vec3> vertices;
    /* Call some function that returns the data as vec3's */
    vector<float> result = move(*((vector<float>*)&vertices));
    return result;
}

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

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

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

Однако я ищу правильный способ достичь чего-то подобного, не полагаясь на конкретную c реализацию STL.

Основная цель этого заключается в том, что существует множество библиотек, которые имеют дело с данными геометрии c, и тратить циклы ЦП просто для обхода проверок типов проблематично c для производительности. Наличие двух разных библиотек, каждый из которых имеет свой собственный тип трехмерного вектора, не имеет значения, когда в конце дня любой такой массив является просто непрерывным массивом с плавающей точкой, где каждые 3 числа представляют позицию вершины.

Можно ли сделать постоянное время построения / реинтерпретации одного вектора одного типа к другому, не полагаясь на UB?

PS: я пытался спросить об этом раньше: Более чистый способ преобразования массива компактных значений с плавающей точкой в ​​массив с плавающей точкой

Но я думаю, что отсутствие контекста делает люди сосредотачиваются на том, что «это не очень хорошая идея», а не на более актуальном вопросе «это работает и необходимо для моего варианта использования, как я могу сделать его лучше?». Вот почему я пытаюсь сделать лучший вопрос с большим количеством контекста и соответствующих примеров.

...