Проблемы с производительностью из-за перегрузки операторов?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Проблемы с производительностью из-за перегрузки операторов?

Сообщение Anonymous »

Моя давняя цель — написать абстракцию для размещения данных и доступа к ним. Поскольку будет задействована некоторая форма перегрузки операторов, я разработал следующий тест производительности:
Рассмотрим следующие две разные версии, определяющие AoS (массив структур):
Первая - это то, как вы это сделаете. это на C:

Код: Выделить всё

struct  C_AoS {
double first, second, third, fourth, fifth;
};

struct ElementAoSstruct {
C_AoS *firstVector;
C_AoS *secondVector;
};
А второй предполагает перегрузку операторов:

Код: Выделить всё

struct AoS_Container2 {
C_AoS* _buffer;
inline C_AoS& operator[](size_t first) const {
return _buffer[first];
}
};

struct Element_AoS_Container2 {
AoS_Container2 firstVector;
AoS_Container2 secondVector;
};
оба выделяются и инициализируются одинаково:

Код: Выделить всё

#define Alignment 64

#define MALLOC_ALIGNED(type, nElements) ((type*) aligned_alloc(Alignment, ((nElements*sizeof(type)-1)/Alignment+1)*Alignment))

ElementAoSstruct *ElementAoS = MALLOC_ALIGNED(ElementAoSstruct, n_Elements);
for (size_t i = 0; i < n_Elements; ++i) {
ElementAoS[i].firstVector = MALLOC_ALIGNED(C_AoS, nDof * 2);
ElementAoS[i].secondVector = &ElementAoS->firstVector[nDof];

for (size_t j = 0; j < nDof * sizeof(C_AoS) / sizeof(double); j++) { ((double *) ElementAoS[i].firstVector)[j] = 1.2431; }
for (size_t j = 0; j < nDof * sizeof(C_AoS) / sizeof(double); j++) { ((double *) ElementAoS[i].secondVector)[j] = 1.2543; }
}

Element_AoS_Container2 *ElementAoS_Abstraction2 = MALLOC_ALIGNED(Element_AoS_Container2, n_Elements);
for (size_t i = 0; i < n_Elements; ++i) {
ElementAoS_Abstraction2[i].firstVector._buffer = MALLOC_ALIGNED(C_AoS, nDof * 2);
ElementAoS_Abstraction2[i].secondVector._buffer = &ElementAoS_Abstraction2[i].firstVector._buffer[nDof];

for (size_t j = 0; j < nDof * sizeof(C_AoS) / sizeof(double); j++) { ((double *) ElementAoS_Abstraction2[i].firstVector._buffer)[j] = 1.2431; }
for (size_t j = 0; j < nDof * sizeof(C_AoS) / sizeof(double); j++) { ((double *) ElementAoS_Abstraction2[i].secondVector._buffer)[j] = 1.2543; }
}
и оба тестируются на одном и том же ядре:

Код: Выделить всё

template 
static void someKernal (T &__restrict firstVector, const T &__restrict secondVector, const size_t length) {

const double factor = 1.1;
for (size_t i{}; i < length; i++) {

firstVector[i].first  += - factor * secondVector[i].first ;
firstVector[i].second += - factor * secondVector[i].second;
firstVector[i].third  += - factor * secondVector[i].third ;
firstVector[i].fourth += - factor * secondVector[i].fourth;
firstVector[i].fifth  += - factor * secondVector[i].fifth ;

}
}
Если я измерю производительность обеих версий, то пойму, что версия с перегрузкой операторов примерно на 40 % медленнее, чем версия "C". Я компилирую с помощью gcc 10.2.1 (-Ofast -march=native). По моему мнению, не должно быть никакой разницы в производительности, я делаю что-то не так с перегрузкой оператора?
Полный код: godbolt.org/z/9an8aWfjc

Подробнее здесь: https://stackoverflow.com/questions/783 ... verloading
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»