Возможна ли когда-нибудь эта методика оптимизации использования памяти в случае союзов? - PullRequest
0 голосов
/ 14 ноября 2010

В случае объектов Union, может ли компилятор быть достаточно умным, чтобы определить, в каких точках используется объем памяти объединения, чтобы оставшаяся память объединения могла использоваться для других целей в качестве оптимизации использования памяти, или это не так даже разрешено из-за того, как стандарт определяет объединение?

Ответы [ 6 ]

1 голос
/ 14 ноября 2010

Теоретически это возможно. Если компилятор достаточно умен для анализа вашей программы и обнаружит, что вы никогда не используете самый большой тип, который он может содержать, он может оптимизировать программу по правилу «как будто». (Поведение программы, за исключением времени, должно быть таким, как если бы оптимизация не проводилась.)

Но вряд ли компилятор сделает это. Это трудно сделать, и это редко когда-либо применимо.

1 голос
/ 14 ноября 2010

Не могу понять, как.

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

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

В таком коде:

{
    union { char c; double d; } x;
    x.c = 1;
    int y;
    some_function(&y);
    std::cout << x.c;
}

Я полагаю, что по правилу «как если бы» компилятор мог уменьшить стек, используемый для x, до 1 байта и использовать память сразу после этого для y.Поскольку адрес x никогда не берется, соответствующая программа не может «наблюдать» разницу, поэтому она действительна.

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

Вы можете подумать, что такая же оптимизация могла бы применятьсяздесь:

{
    union { char c; double d; } x;
    x.c = 1;
    int y;
    some_function(&y);
    std::cout << x.c;
    x.d = 1.0;
    std::cout << x.d;
}

но что если some_function сохранит копию указателя на y, возможно, в глобальном?Затем, если перегруженный operator<< может в итоге косвенно вызвать любой код, использующий этот указатель, компилятор не может перезаписать память.Я сомневаюсь, что любая реализация может быть полностью встроенной std::cout << x.d, поэтому даже если этого не произойдет, компилятор не узнает, что это не так, и не сможет выполнить оптимизацию.

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

1 голос
/ 14 ноября 2010

Союз резервирует место, достаточное для хранения самого большого из его членов 1 . Таким образом, по определению, одно и то же место зарезервировано для union { double a; byte b } независимо от того, сохранено ли оно через дубль или байт.

Старайтесь не думать о объединении как о типе варианта, который может быть или байтом, или двойным, или целым числом, в зависимости от того, какой член вы написали в последний раз. Фактически это механизм наложения нескольких разных типов данных на одну и ту же область памяти, так что эта область является одновременно с плавающей точкой, а также с типом int и what-have-you в своего рода квантовом наложении. Это особенно полезно для type-punning , когда вам нужно обойти систему типов языка.

1 ANSI / ISO 9899.

1 голос
/ 14 ноября 2010

номер

Для этого компилятор должен знать, что вы «используете» в любой момент времени. Как это возможно? Что если вы использовали «неиспользуемый» раздел для своих собственных оптимизаций?

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

Нет, не совсем. Компилятор не может узнать в любой момент времени, сколько места используется. Тем не менее, нет смысла использовать объединение в C ++, так как он принимает только типы POD (чуть менее ограничен в C ++ 0x), а с такими типами boost :: option и boost :: any нет нужды особенность языка.

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

Нет, объединение выравнивается в соответствии с требованиями выравнивания его самого большого члена.

...