Это работает, но нет никакой гарантии, что оптимтзатор развернет цикл. А если не развернет, то это — 30-50% потери производительности. А хотелось бы с гарантией, чтобы статически, как в MACRO-11, типа:
MS>Это работает, но нет никакой гарантии, что оптимтзатор развернет цикл. А если не развернет, то это — 30-50% потери производительности. А хотелось бы с гарантией, чтобы статически, как в MACRO-11, типа:
ну а если применить Duff's Device?
в твоём случае это будет выглядеть примерно так:
(код не компилил)
template<typename T, size_t N>
inline
unsigned read_value(char const * ptr, T(&ret_val)[N])
{
char* to = (char*)ret_val;
unsigned n = (N+7)/8;
switch (N%8)
{
case 0:do{*to = *ptr++; to++;
case 7:*to = *ptr++; to++;
case 6:*to = *ptr++; to++;
case 5:*to = *ptr++; to++;
case 4:*to = *ptr++; to++;
case 3:*to = *ptr++; to++;
case 2:*to = *ptr++; to++;
case 1:*to = *ptr++; to++;
} while(--n>0);
}
return N;
}
вот здесь историческая справка про Duff's Device
вот здесь Александреску использует его.
Re[2]: Эх, не хватает в C++ макроассемблерных макросов :)
Здравствуйте, korzhik, Вы писали:
k>ну а если применить Duff's Device?
duffdevice — мертв. Его использование — это навешивание гирь на ноги оптимизатору.
Циклы for компилятор развернет сам. Поставив правильные #pragma Intel C++ Compiler еще и равернет его в SSE код.
Не сработает. ptr имеет право быть невыровненным на границу sizeof(T). Любой RISC от этого сразу вылетит по автобусной ошибке.
Или reinterpret_cast такой умный, что скопирует побайтно, типа memcpy? Что-то не внушает доверия.
Кроме того, вместо ptr может быть итератор. В этом случае вообще не гарантировано, что байты расположениы в памяти подряд (std::deque, std::list).
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: Эх, не хватает в C++ макроассемблерных макросов :)
MS>Не сработает. ptr имеет право быть невыровненным на границу sizeof(T). Любой RISC от этого сразу вылетит по автобусной ошибке. MS>Или reinterpret_cast такой умный, что скопирует побайтно, типа memcpy? Что-то не внушает доверия.
Ничего он не скопирует, как раз он — "глупый", фактического преобразования как раз не выполняется.
И Страуструп писал, что это практически ВСЕГДА не переносимо.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: Эх, не хватает в C++ макроассемблерных макросов :)
Здравствуйте, _Winnie, Вы писали:
_W>Здравствуйте, korzhik, Вы писали:
k>>ну а если применить Duff's Device?
_W>duffdevice — мертв. Его использование — это навешивание гирь на ноги оптимизатору. _W>Циклы for компилятор развернет сам. Поставив правильные #pragma Intel C++ Compiler еще и равернет его в SSE код.
Насчёт мёртвости Duff's device ничего конкретного сказать не могу, это сложный вопрос, надо исследовать.
вот здесь Александреску как раз сравнивает простой цикл и Duff's device.
Я думаю всё зависит какая задача стоит:
если стоит задача оптимизировать код под конкретную платформу и компилятор, то конечно Duff's device использовать не надо.
Но если стоит задача оптимизировать кроссплатформенный код, то Duff's device может пригодиться.
2McSeem2:
Я думаю лучший вариант будет такой:
вам надо сделать частичную специализацию для POD и в ней использовать memcpy,
а для не POD использовать Duff's device.
Re[3]: Эх, не хватает в C++ макроассемблерных макросов :)
Здравствуйте, McSeem2, Вы писали:
MS>Не сработает. ptr имеет право быть невыровненным на границу sizeof(T).
Как он может быть невыровненным, если судя по коду там лежит T?
MS>Кроме того, вместо ptr может быть итератор. В этом случае вообще не гарантировано, что байты расположениы в памяти подряд (std::deque, std::list).
Если там будет итератор, то будет другое решение
Как все запущенно...
Re[4]: Эх, не хватает в C++ макроассемблерных макросов :)
Здравствуйте, Владик, Вы писали:
MS>>Не сработает. ptr имеет право быть невыровненным на границу sizeof(T).
В>Как он может быть невыровненным, если судя по коду там лежит T?
В ptr лежат байты. Сначала там bool, потом int, потом — double. И все плотно упаковано.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[2]: Эх, не хватает в C++ макроассемблерных макросов :)
Здравствуйте, sergey_shandar, Вы писали:
_>PS. Смысл read_value не важен, только хотел показать идею развернутого цикла с большим количеством итераций ~ 1024.
Тоже не фонтан, увы. Этот switch, IMO, еще сложнее поддается оптимизации, чем простой for, с константой
i < sizeof(T).
Что там компилятор сделает для switch — бинарный поиск? Для копирования одного инта — очень накладно. А сумеет ли компилятор определить, что можно применить приямой вычисляемый jmp — это еще большой вопрос. Вот если бы был еще вычисляемый goto в явном виде, как в Фортране или PL/I...
Вообще, странно, что Керниган с Ричи, как поклонники PDP и MACRO-11 не встроили изначально в препроцессор мощных макро-средств, по типу макроассемблерных. Так же, непонятно, почему не сделали вычисляемого goto, вместо чего приходится использовать вульгарную duff's машину, которая на самом деле ничего не гарантирует, тем более — на тогдашнем уровне возможностей оптимизации компиляторов. Да и вообще, изначальный PDP-шный компилятор с C был на редкость убогим и неэффективным по сравнению со стандарным Фортраном...
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re: Эх, не хватает в C++ макроассемблерных макросов :)