быстрое копирование памяти
От: Аноним  
Дата: 11.08.05 09:34
Оценка:
сравните две строчки (p1,p2 какие-то буфера нужного размера):

1. ::memcpy( p1, p2, 8 );
2. *( double* )p1 = *( double* )p2;

всегда ли 2-я будет работать
и быстрее ли?
Re: быстрое копирование памяти
От: Аноним  
Дата: 11.08.05 09:48
Оценка: 1 (1)
А>всегда ли 2-я будет работать
А>и быстрее ли?

Если p1 и p2 не обладают выравниванием, подходящим для double, это будет плохо
Re[2]: быстрое копирование памяти
От: Аноним  
Дата: 11.08.05 12:34
Оценка:
А>Если p1 и p2 не обладают выравниванием, подходящим для double, это будет плохо

Э..., что это значит выравнивание, подходящее для double?

Я подразумевал, что p1 и p2 это просто void*,
указывающие на какую-либо память (байтовые массивы например),
насколько важно на что они конкретно указывают?
Re[3]: быстрое копирование памяти
От: MaximE Великобритания  
Дата: 11.08.05 12:58
Оценка:
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 гарантированно соответствуют этому требованию?
Re[4]: быстрое копирование памяти
От: Lorenzo_LAMAS  
Дата: 11.08.05 13:04
Оценка:
ME>sizeof(double)

Вообще говоря неверно.

#include <iostream>

struct test
{
    double d_;
    int i_;
};

int main()
{
    std::cout<<sizeof(double)<<' '<<sizeof(int)<<' '<<sizeof(test)<<std::endl;
}

Результат 8 4 12
Of course, the code must be complete enough to compile and link.
Re: быстрое копирование памяти
От: MaximE Великобритания  
Дата: 11.08.05 13:07
Оценка:
wrote:

> сравните две строчки (p1,p2 какие-то буфера нужного размера):

>
> 1. ::memcpy( p1, p2, 8 );
> 2. *( double* )p1 = *( double* )p2;
>
> всегда ли 2-я будет работать
> и быстрее ли?

2 — будет работать иногда.
memcpy работает независимо от выравнивания данных и обычно заоптимизирован чтобы копировать машинными словами или используя mmx/sse/sse2/....

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[5]: быстрое копирование памяти
От: MaximE Великобритания  
Дата: 11.08.05 13:18
Оценка:
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 ];

и я их копирую так:

int iBufsSizeRest = 20;
int iDblSize = sizeof( double );
while( iBufsSizeRest < iDblSize )
{
*( double* )pbBuf1 = *( double* )pbBuf2;
pbBuf1 += iDblSize;
pbBuf2 += iDblSize;
iBufsSize -= iDblSize;
}
::memcpy( pbBuf1, pbBuf2, iBufSizeRest );

это будет работать, или что-то здесь не так?
Re[2]: быстрое копирование памяти
От: Аноним  
Дата: 11.08.05 14:26
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>2 — будет работать иногда.

ME>memcpy работает независимо от выравнивания данных и обычно заоптимизирован чтобы копировать машинными словами или используя mmx/sse/sse2/....

аа, если машинными словами..., то это другое дело,
я заходил тут в один memcpy, он там просто побайтно
бежал и копировал, я вот хотел ему помочь
Re[4]: быстрое копирование памяти
От: Alex Alexandrov США  
Дата: 17.08.05 18:04
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>На x86 можно читать невыровненные данные. На x86-64 и многих остальных платформах — нельзя, получишь SIGSEGV.


SIGBUS вообще-то. По крайней мере, на Итаниуме.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
It's kind of fun to do the impossible (Walt Disney)
Re: быстрое копирование памяти через FPU ЧЕРЕВАТО!!!
От: Erop Россия  
Дата: 17.08.05 18:26
Оценка: 7 (2)
Здравствуйте, Аноним, Вы писали:

А>сравните две строчки (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. И данные потерять и непонятное поведение огрести . Короче говоря с просто битами так делать не хорошо.

вот этого я и опасался,
ну возьмем тогда long
Re[5]: быстрое копирование памяти
От: Evgeniy13 Россия  
Дата: 18.08.05 15:02
Оценка:
Это будет работать, но медленнее, чем один вызов memcpy.
Не все в этом мире можно выразить с помощью нулей и единиц...
Re[3]: быстрое копирование памяти через FPU ЧЕРЕВАТО!!!
От: Аноним  
Дата: 18.08.05 17:12
Оценка: +2
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Erop, Вы писали:


E>>2) Про быстрее вообще говоря действительно зависит от выравнивания исходного и целевого буфера. Но если тебе надо переслать именно 8 байт, то очень может быть, что и всегда быстрее . При этом оно ещё и целочисленное устройство может не грузить, так что с чем-нибудь полезным ещё и спарится (это если речь про x86 )


А>ага, значит быстрее все-таки,

А>не знаю, что все так к выравниванию прицепились,
А>копируется в общем случае N байт, остаток отдельно,
А>главное основную часть быстро скопировать

E>>1) А вот работать может не всегда. Во всяком случае на x86 если )

E>>Действительно, второй вариант кода он ведь могёт скомпилироваться оптимизирующим компилятором в загрузку регистра FPU из памяти и выгрузку по другому адресу (если скомпилируется просто в пересылки слов, то вообще-то смысла в такой оптимизвции не много). А вот тут начнутся вилы. Дело в том, что далеко не все последовательности 80 бит являются валидными double, так что можно легко и непринуждённо напороться на ошибку FPU. И данные потерять и непонятное поведение огрести . Короче говоря с просто битами так делать не хорошо.

А>вот этого я и опасался,

А>ну возьмем тогда long

Оставьте лучше memcpy. Реально быстрее у вас не будет (медленнее на порядок — запросто), а ошибок наделаете. Других забот нет?
Re[3]: быстрое копирование памяти через FPU ЧЕРЕВАТО!!!
От: Erop Россия  
Дата: 18.08.05 17:23
Оценка:
Здравствуйте, Аноним, Вы писали:

А>ну возьмем тогда long



Ну а тогда и memcpy сойдёт. И понятнее и предсказуемее. И если на архитектуре словами веселее выходит, то memcpy словами копировать будет
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: быстрое копирование памяти через FPU ЧЕРЕВАТО!!!
От: Erop Россия  
Дата: 18.08.05 17:29
Оценка:
Здравствуйте, Аноним, Вы писали:

А>ага, значит быстрее все-таки,

А>не знаю, что все так к выравниванию прицепились,
А>копируется в общем случае N байт, остаток отдельно,
А>главное основную часть быстро скопировать

1) Быстрее может быть из-за FPU и если всё в кэше, а так один хрен как через проц гнать -- гнлавное до него пошине дотащить и обратно.
2) Чего все к выравниванию прицепились. Есть две причины. Обе архитектурного толка.
Причина №1 состоит в том, что реально проц с памятью обменивается не байтами, а словами или даже большими пачками бит. Но это только выровнеными словами. Поэтому если вы читаете выравненное слово, то это происходит за один цикл общения с памятью, а если таки невыравнное, то за два. В результате в два раза медленне. А если байт, то всегда за один, но только байт.
Скажем тачка 32-битная. Тогда при побайтовой пересылке за цикл обмена с памятью прокачаете 8 бит, при невыравненной пословной, в среднем 16, а при выравненной пословной 32 -- в разы эффект-то
Причина №2 состоит в том, что всякие там кэши и прочие архитектурные излишества тоже ориентированы на последовательный пословный доступ по выровненным словам. Так что если начнёшь по невыровненным словам читать/писать, то можешь ещё и кэш сделать неэффективным, что вообще всё на корню погубит.

Короче memcpy почти всегда неплох, основной его недостаток -- плохая читабельность и большая опасность ошибиться. Короче низкоуровневое для плюсов средсвто.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: быстрое копирование памяти
От: arcman Россия  
Дата: 19.08.05 08:30
Оценка:
Здравствуйте, MaximE, Вы писали:


ME>memcpy работает независимо от выравнивания данных и обычно заоптимизирован чтобы копировать машинными словами или используя mmx/sse/sse2/....

Скорее memcpy иногда "заоптимизирован".

Здравствуйте, Erop, Вы писали:
E>(если скомпилируется просто в пересылки слов, то вообще-то смысла в такой оптимизвции не много)
Смысла почти в четыре раза — копирование двойными словами происходит гораздо быстрее нежели просто побайтно и является одним из самых оптимальных вариантов копирования памяти.

E>И если на архитектуре словами веселее выходит, то memcpy словами копировать будет

Мы не в сказке живём, memcpy копирует побайтово.

E>плохая читабельность и большая опасность ошибиться

Это ты круто загнул

сравним:
char *p1, *p2;
....
memcpy(p1, p2, 8);

или:
....
*(((dword*)p1)++) = *(((dword*)p2)++);
*(dword*)p1 = *(dword*)p2;


2ALL:
Есть хорошая, полностью практическая, книжка дающая однозначные ответы и рекомендации на subj
"Крис Касперски — Техника оптимизации программ. Эффективное использование памяти" http://findbook.ru/search/d0?s=1&amp;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&amp;r=0&amp;ptype=1)
Все аспекты связанные с копированием памяти там подробно разобраны.
Книга существует также в электронном виде, но администрация форума неразрешает её публиковать. Если автор разрешит публикацию в интернете, то я выложу линки
Re[3]: быстрое копирование памяти
От: CrystaX Россия https://crystax.me/
Дата: 19.08.05 08:36
Оценка:
memcpy может копировать не только побайтово. Смотри здесь
Автор: Mr. None
Дата: 16.08.05
.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[3]: быстрое копирование памяти
От: CrystaX Россия https://crystax.me/
Дата: 19.08.05 08:52
Оценка: -1
Здравствуйте, arcman, Вы писали:

A>2ALL:

A>Есть хорошая, полностью практическая, книжка дающая однозначные ответы и рекомендации на subj
A>"Крис Касперски — Техника оптимизации программ. Эффективное использование памяти" http://findbook.ru/search/d0?s=1&amp;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&amp;r=0&amp;ptype=1)
A>Все аспекты связанные с копированием памяти там подробно разобраны.
A>Книга существует также в электронном виде, но администрация форума неразрешает её публиковать. Если автор разрешит публикацию в интернете, то я выложу линки

Насчет этой книги уже все сказали здесь
Автор: Alex Alexandrov
Дата: 17.08.05
.
... << RSDN@Home 1.1.4 stable rev. 510>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.