Если p1 и p2 не обладают выравниванием, подходящим для double, это будет плохо
Re[2]: быстрое копирование памяти
От:
Аноним
Дата:
11.08.05 12:34
Оценка:
А>Если p1 и p2 не обладают выравниванием, подходящим для double, это будет плохо
Э..., что это значит выравнивание, подходящее для double?
Я подразумевал, что p1 и p2 это просто void*,
указывающие на какую-либо память (байтовые массивы например),
насколько важно на что они конкретно указывают?
wrote:
> > А>Если p1 и p2 не обладают выравниванием, подходящим для double, это будет плохо > > Э..., что это значит выравнивание, подходящее для double?
sizeof(double)
> Я подразумевал, что p1 и p2 это просто void*, > указывающие на какую-либо память (байтовые массивы например), > насколько важно на что они конкретно указывают?
На x86 можно читать невыровненные данные. На x86-64 и многих остальных платформах — нельзя, получишь SIGSEGV.
-- Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[3]: быстрое копирование памяти
От:
Аноним
Дата:
11.08.05 13:00
Оценка:
Здравствуйте, Аноним, Вы писали:
А>>Если p1 и p2 не обладают выравниванием, подходящим для double, это будет плохо
А>Э..., что это значит выравнивание, подходящее для double?
А>Я подразумевал, что p1 и p2 это просто void*, А>указывающие на какую-либо память (байтовые массивы например), А>насколько важно на что они конкретно указывают?
У типа double есть свое выравнивание. Вот что говорит стандарт про выравнивание
3.9/5
Object types have alignment requirements (3.9.1, 3.9.2). The alignment of a complete object type is an
implementation-defined integer value representing a number of bytes; an object is allocated at an address
that meets the alignment requirements of its object type.
Допустим, у меня выравнивание для double — 8. Это означает, что адрес double должен быть кратен 8. А у тебя указатели p1 и p2 гарантированно соответствуют этому требованию?
wrote:
> сравните две строчки (p1,p2 какие-то буфера нужного размера): > > 1. ::memcpy( p1, p2, 8 ); > 2. *( double* )p1 = *( double* )p2; > > всегда ли 2-я будет работать > и быстрее ли?
2 — будет работать иногда.
memcpy работает независимо от выравнивания данных и обычно заоптимизирован чтобы копировать машинными словами или используя mmx/sse/sse2/....
Lorenzo_LAMAS wrote:
> ME>sizeof(double) > > Вообще говоря неверно.
Эта формула дает alignment, который гарантированно подходит для встроенных типов.
-- Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[4]: быстрое копирование памяти
От:
Аноним
Дата:
11.08.05 14:24
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Допустим, у меня выравнивание для double — 8. Это означает, что адрес double должен быть кратен 8. А у тебя указатели p1 и p2 гарантированно соответствуют этому требованию?
ну я, как бы думал что это вне вопроса, я же писал, что буферы достаточного размера,
естественно для произвольного буфера я делю размер на размер дабла и остаток копирую отдельно,
я пока не очень понял при чем здесь выравнивание,
предположим у меня есть два буфера:
BYTE* pbBuf1 = new BYTE[ 20 ];
BYTE* pbBuf2 = new BYTE[ 20 ];
Здравствуйте, MaximE, Вы писали:
ME>2 — будет работать иногда. ME>memcpy работает независимо от выравнивания данных и обычно заоптимизирован чтобы копировать машинными словами или используя mmx/sse/sse2/....
аа, если машинными словами..., то это другое дело,
я заходил тут в один memcpy, он там просто побайтно
бежал и копировал, я вот хотел ему помочь
Здравствуйте, Аноним, Вы писали:
А>сравните две строчки (p1,p2 какие-то буфера нужного размера):
А>1. ::memcpy( p1, p2, 8 ); А>2. *( double* )p1 = *( double* )p2;
А>всегда ли 2-я будет работать А>и быстрее ли?
2) Про быстрее вообще говоря действительно зависит от выравнивания исходного и целевого буфера. Но если тебе надо переслать именно 8 байт, то очень может быть, что и всегда быстрее . При этом оно ещё и целочисленное устройство может не грузить, так что с чем-нибудь полезным ещё и спарится (это если речь про x86 )
1) А вот работать может не всегда. Во всяком случае на x86 если )
Действительно, второй вариант кода он ведь могёт скомпилироваться оптимизирующим компилятором в загрузку регистра FPU из памяти и выгрузку по другому адресу (если скомпилируется просто в пересылки слов, то вообще-то смысла в такой оптимизвции не много). А вот тут начнутся вилы. Дело в том, что далеко не все последовательности 80 бит являются валидными double, так что можно легко и непринуждённо напороться на ошибку FPU. И данные потерять и непонятное поведение огрести
Короче говоря с просто битами так делать не хорошо.
3) Додаток, хоть и не просили
Пишем так:
struct DangerousData {
int i1;
int i2;
double d1;
};
void f( DangerousData );
void g()
{
DangerousData data;
f( data ); // Тут иногда всё дохнет :(
}
Кто-то, я не помню кто и при каких настройках, но типа VC7.1 при максимальной оптимизации по скорости (хотя точно не помню) выдавал такой трюк:
а) Генерил copy-constructor DangerousData, в котором целые копировал через пересылки, а double через FPU.
б) Если структура была не инициализирована, то иногда всё вылетало по ошибке FPU.
в) Ну а вылетало там, где стоит комментарий
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: быстрое копирование памяти через FPU ЧЕРЕВАТО!!!
От:
Аноним
Дата:
18.08.05 11:15
Оценка:
Здравствуйте, Erop, Вы писали:
E>2) Про быстрее вообще говоря действительно зависит от выравнивания исходного и целевого буфера. Но если тебе надо переслать именно 8 байт, то очень может быть, что и всегда быстрее . При этом оно ещё и целочисленное устройство может не грузить, так что с чем-нибудь полезным ещё и спарится (это если речь про x86 )
ага, значит быстрее все-таки,
не знаю, что все так к выравниванию прицепились,
копируется в общем случае N байт, остаток отдельно,
главное основную часть быстро скопировать
E>1) А вот работать может не всегда. Во всяком случае на x86 если ) E>Действительно, второй вариант кода он ведь могёт скомпилироваться оптимизирующим компилятором в загрузку регистра FPU из памяти и выгрузку по другому адресу (если скомпилируется просто в пересылки слов, то вообще-то смысла в такой оптимизвции не много). А вот тут начнутся вилы. Дело в том, что далеко не все последовательности 80 бит являются валидными double, так что можно легко и непринуждённо напороться на ошибку FPU. И данные потерять и непонятное поведение огрести . Короче говоря с просто битами так делать не хорошо.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Erop, Вы писали:
E>>2) Про быстрее вообще говоря действительно зависит от выравнивания исходного и целевого буфера. Но если тебе надо переслать именно 8 байт, то очень может быть, что и всегда быстрее . При этом оно ещё и целочисленное устройство может не грузить, так что с чем-нибудь полезным ещё и спарится (это если речь про x86 )
А>ага, значит быстрее все-таки, А>не знаю, что все так к выравниванию прицепились, А>копируется в общем случае N байт, остаток отдельно, А>главное основную часть быстро скопировать
E>>1) А вот работать может не всегда. Во всяком случае на x86 если ) E>>Действительно, второй вариант кода он ведь могёт скомпилироваться оптимизирующим компилятором в загрузку регистра FPU из памяти и выгрузку по другому адресу (если скомпилируется просто в пересылки слов, то вообще-то смысла в такой оптимизвции не много). А вот тут начнутся вилы. Дело в том, что далеко не все последовательности 80 бит являются валидными double, так что можно легко и непринуждённо напороться на ошибку FPU. И данные потерять и непонятное поведение огрести . Короче говоря с просто битами так делать не хорошо.
А>вот этого я и опасался, А>ну возьмем тогда long
Оставьте лучше memcpy. Реально быстрее у вас не будет (медленнее на порядок — запросто), а ошибок наделаете. Других забот нет?
Re[3]: быстрое копирование памяти через FPU ЧЕРЕВАТО!!!
Здравствуйте, Аноним, Вы писали:
А>ну возьмем тогда long
Ну а тогда и memcpy сойдёт. И понятнее и предсказуемее. И если на архитектуре словами веселее выходит, то memcpy словами копировать будет
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: быстрое копирование памяти через FPU ЧЕРЕВАТО!!!
Здравствуйте, Аноним, Вы писали:
А>ага, значит быстрее все-таки, А>не знаю, что все так к выравниванию прицепились, А>копируется в общем случае N байт, остаток отдельно, А>главное основную часть быстро скопировать
1) Быстрее может быть из-за FPU и если всё в кэше, а так один хрен как через проц гнать -- гнлавное до него пошине дотащить и обратно.
2) Чего все к выравниванию прицепились. Есть две причины. Обе архитектурного толка.
Причина №1 состоит в том, что реально проц с памятью обменивается не байтами, а словами или даже большими пачками бит. Но это только выровнеными словами. Поэтому если вы читаете выравненное слово, то это происходит за один цикл общения с памятью, а если таки невыравнное, то за два. В результате в два раза медленне. А если байт, то всегда за один, но только байт.
Скажем тачка 32-битная. Тогда при побайтовой пересылке за цикл обмена с памятью прокачаете 8 бит, при невыравненной пословной, в среднем 16, а при выравненной пословной 32 -- в разы эффект-то
Причина №2 состоит в том, что всякие там кэши и прочие архитектурные излишества тоже ориентированы на последовательный пословный доступ по выровненным словам. Так что если начнёшь по невыровненным словам читать/писать, то можешь ещё и кэш сделать неэффективным, что вообще всё на корню погубит.
Короче memcpy почти всегда неплох, основной его недостаток -- плохая читабельность и большая опасность ошибиться. Короче низкоуровневое для плюсов средсвто.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
ME>memcpy работает независимо от выравнивания данных и обычно заоптимизирован чтобы копировать машинными словами или используя mmx/sse/sse2/....
Скорее memcpy иногда "заоптимизирован".
Здравствуйте, Erop, Вы писали: E>(если скомпилируется просто в пересылки слов, то вообще-то смысла в такой оптимизвции не много)
Смысла почти в четыре раза — копирование двойными словами происходит гораздо быстрее нежели просто побайтно и является одним из самых оптимальных вариантов копирования памяти.
E>И если на архитектуре словами веселее выходит, то memcpy словами копировать будет
Мы не в сказке живём, memcpy копирует побайтово.
E>плохая читабельность и большая опасность ошибиться
Это ты круто загнул
Здравствуйте, arcman, Вы писали:
A>2ALL: A>Есть хорошая, полностью практическая, книжка дающая однозначные ответы и рекомендации на subj A>"Крис Касперски — Техника оптимизации программ. Эффективное использование памяти" http://findbook.ru/search/d0?s=1&pvalue=%D2%E5%F5%ED%E8%EA%E0+%EE%EF%F2%E8%EC%E8%E7%E0%F6%E8%E8+%EF%F0%EE%E3%F0%E0%EC%EC&r=0&ptype=1) A>Все аспекты связанные с копированием памяти там подробно разобраны. A>Книга существует также в электронном виде, но администрация форума неразрешает её публиковать. Если автор разрешит публикацию в интернете, то я выложу линки