Изменение выравнивания в производном типе - PullRequest
0 голосов
/ 19 декабря 2018

Скажем, у вас есть эти два типа:

struct alignas(8) Base { double a; double b; }
struct alignas(16) Derived : public Base {}

И эти функции:

void Foo(Base b)
void Bar(Base* start, Base* end)

Законно ли совершать звонки, такие как

Foo(someDerived)
Bar(someDerivedArray, someDerivedArray + arrayLength)

во всехслучаи?Зависит ли это от содержимого Base и конкретных ограничений выравнивания?Я мог бы видеть, что есть проблема, если бы derived были, скажем, 32-битными выровненными, потому что тогда был бы промежуток между элементами someDerivedArray, и Bar не знал бы об этом разрыве, поэтомуЯ предполагаю, что это неопределенное поведение, но я не уверен.

XY объяснение: мы используем библиотеку Thrust GPGPU, и ее сложный тип имеет несовместимые выравнивания между кодом устройства и кодом хоста;мы пытаемся выяснить, как обойти эту проблему.Один из вариантов - определить наш собственный сложный тип, производный от thrust::complex, но с тем же спецификатором выравнивания и использовать его, но, конечно, различные функции тяги ожидают thrust::complex, поэтому мы будем нарезать или приводить в менее выровненныйтип.

1 Ответ

0 голосов
/ 19 декабря 2018

alignas применяется только к базовым и производным;Они не относятся к своим членам: a и b.

Так что проблем нет.

#include <iostream>

using namespace std;

struct A
{
    int x, y, z, w;
};

struct alignas(64) B
{
    alignas(64) int x;
    alignas(64) float y, z, w;
};

struct alignas(64) C : public A
{
};

int main()
{
A a;
B b;
C c;
cout << size_t((char*)(void*)&(a.y)-(char*)(void*)&(a.x)) << endl;
cout << size_t((char*)(void*)&(b.y)-(char*)(void*)&(b.x)) << endl;
cout << size_t((char*)(void*)&(c.y)-(char*)(void*)&(c.x)) << endl;  
return 0;
}

Возвращает

4
64
4

Edit : если вы мне не верите, запустите код самостоятельно.Я не уверен, почему кто-то мог подумать, что alignas обеспечит выравнивание для каждого члена класса.Определение alignas гласит, что оно применяется к самому классу (только на выравнивание класса влияет выравнивание его членов, а не членов, на которые влияет класс).

Редактировать 2 : в отношении Thrust - если устройство и хост выбирают разные выравнивания в классах, это является ошибкой согласованности разных компиляторов, которые должны быть синхронизированы.Вы можете отправить сообщение об ошибке в NVIDIA, поскольку это является их проблемой.

Как обойти такие проблемы?Это сложный вопрос ... удачи.

...