Как мои объявления переменных влияют на время выполнения

Я разработчик схем (а не мастер программного обеспечения) и работал над численным алгоритмом за последние 9 месяцев. В качестве способа оценки эффективности моих алгоритмов я отслеживаю количество времени, необходимое для слияния с решением.

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

int N, j, Iter;
long ****** RealZero, RealErr, QuadIterErr, QuadX;
long ****** TUV[3], QuadQP[102], RealQP[102];
bool Updated;
int N, j, Iter;
long ****** RealZero, RealErr, QuadIterErr, QuadX;
long ****** QuadQP[102], RealQP[102];
bool Updated;
long ****** TUV[3];

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

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

Может кто-нибудь дать мне некоторое представление о том, что может происходить здесь и как его исправить?

Мне нужна консистенция больше, чем мне нужна скорость. Я не использую оптимизаторы скорости (настройки компилятора по умолчанию), и я использую С++ Builder XE3. Я не использую пакет #pragma (как кто-то спросил).

На основе комментариев я настраиваю объявления для медленного и быстрого выполнения и сравнивает базовые адреса во всех длинных двойных переменных. Независимо от того, медленный или быстрый, адреса заканчиваются на 0, 4, 8 или C.

2 ответа

Одной вещью, которая определенно влияет на производительность кода, являются неуравновешенные данные: платформа x86 может считывать неизменные данные (в отличие от некоторых других архитектур), но будет страдать от снижения производительности.

Что такое несвязанный доступ? Когда размер типа не сохраняется по адресу, который кратен этому размеру. Поэтому, если вы храните 32-разрядное целое по нечетному адресу или даже на четном адресе, который не является кратным 4, CPU может потребоваться сделать два чтения в памяти, чтобы получить обе половины данных.

В этом случае размер long ****** равен 8, поэтому вы хотите, чтобы они хранились по адресам с кратным 8, но первые три переменные являются целыми числами, что составляет 12, поэтому в первом блоке определения все длинных удвоений сохраняются на адресах не выровненных адресов.

Второй блок определений, по-видимому, не слишком отличается, но bool переместился вверх, сделав теперь TUV полностью выровненным. Если TUV была наиболее часто используемой памятью в алгоритме, то я вполне мог поверить, что была разница во времени!

Итак, как вы это исправите? Либо сообщите компилятору, чтобы хранить переменные с большим выравниванием (обратите внимание, что это не связано с упаковкой - это связано с хранением в структуре) или, по крайней мере, сначала помещают все наиболее типичные переменные в объявления.


user5108_Dan сказал:

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

Это, скорее всего, ваша проблема. Поскольку производственный код всегда будет оптимизирован, не выполняйте свои тесты скорости по неоптимизированному коду: вы, по сути, выполняете работу компилятора!

licensed under cc by-sa 3.0 with attribution.