Можно ли получить доступ к внутренним значениям переменной __m128 в качестве атрибута в классе C ++? - PullRequest
3 голосов
/ 11 февраля 2012

Я бы хотел, чтобы класс Vector (который представляет вектор из 3-х чисел) был реализован с использованием встроенных функций SSE (поэтому я не буду использовать 4-й элемент типа __m128). Но я хотел бы иметь возможность легко получить к ним доступ, например, к атрибутам: поэтому myVector.x будет обращаться к 0-31 битам в vec, myVector.y будет обращаться к 32-63 битам в vec, но без необходимости вызывать некоторые getX () метод. Атрибут 'x' будет своего рода псевдонимом для 0-31 битов 'vec'. Возможно ли это?

class Vector {  
public:  
  float x;  
  float y;  
  float z;  
private:  
  __m128 vec;  
}

Ответы [ 3 ]

7 голосов
/ 11 февраля 2012

Нет, поскольку это нарушает правило строгого наложения .

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

См. Что такое строгое правило наложения имен?

(Согласно правилу доступ с использованием объединения безопасен, но это применимо только в том случае, если вы называете объединение. Получение указателя или ссылки на член объединения, а затем последующее использование указателя или ссылки непосредственно не безопасно.)

1 голос
/ 11 февраля 2012

Возможно, вы могли бы использовать union , что-то вроде

union data
{
    float[4] xyz;
    __m128 vec;
} aVec;

Тогда значения с плавающей точкой будут aVec.xyz[0], aVec.xyz[1] и aVec.xyz[2], а __m128 будет aVec.vec. Массив float состоит из четырех элементов, но ничто не говорит о том, что вы должны использовать четвертый.

0 голосов
/ 29 марта 2019

Вы можете написать структуру, которая автоматически конвертирует в и из __m128:

struct alignas(16) Vec4f
{
    float x, y, z, w;
    operator __m128() const { return _mm_load_ps(&x);}
    Vec4f(__m128 const v) { _mm_store_ps(&x, v);}
};

Это имеет тот недостаток, что Vec4f будет передаваться через два регистра SSE вместо одного (при передаче по значению).: https://godbolt.org/z/sutmuM).

В целом, я бы предложил создать структуру, которая бы содержала только методы __m128 и overload x(), y() и т. Д. Элементные операции над регистрами SSE должны бытьпо возможности избегать (за исключением использования нулевого элемента).

Примечание: alignas(16) требует C ++ 11, для большинства компиляторов существуют специфичные для компилятора альтернативы. В качестве альтернативы вы можете использовать _mm_loadu_ps и _mm_storeu_ps вместо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...