Модераторы: JackYF, bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> memcpy, реализация под VS (2010) 
:(
    Опции темы
ForceKeeper
Дата 6.9.2011, 02:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 17.3.2010
Где: Минск

Репутация: нет
Всего: нет



Из праздного интереса сравнил производительность на своем ПК родного memcpy и такого цикла
Код

short* destination = (short*)mas;
short* source = (short*)mas + 300000;
for(int i = 0; i < 700000; ++i)
destination[i] = source[i];

Дефолтная функция оказалась в 10-11 раз быстрее. Может кто знает, что за сильное колдунство в ней применено?

P.S.
mas - интовский массив, так что, если я ничего не путаю, проблем с выравниванием по вордам не должно быть

PM MAIL WWW   Вверх
boostcoder
Дата 6.9.2011, 02:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



копирование двойными словами или четвертными словами.
PM WWW   Вверх
newbee
Дата 6.9.2011, 02:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: 3
Всего: 19



AFAIK в memcpy используются какие-то специальные ассемблерные функции. Как msvc не знаю, а GCC при -03 выравнивает производительность memcpy и наколеночной реализации.

Добавлено через 1 минуту и 9 секунд
Утром исходник посмотрю.


--------------------
You're face to face
With man who sold the world
PM   Вверх
volatile
Дата 6.9.2011, 02:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(ForceKeeper @  6.9.2011,  02:44 Найти цитируемый пост)
Может кто знает, что за сильное колдунство в ней применено

Посмотрите исходники. все ран-таймовские сорцы должны быть. 
Вот исходник от 2008 студии (2010 под рукой нет, но думаю там ничего кардинального с memcpy не произошло)
Код

void * __cdecl memcpy (
        void * dst,
        const void * src,
        size_t count
        )
{
        void * ret = dst;

#if defined (_M_IA64)

        {


        __declspec(dllimport)


        void RtlCopyMemory( void *, const void *, size_t count );

        RtlCopyMemory( dst, src, count );

        }

#else  /* defined (_M_IA64) */
        /*
         * copy from lower addresses to higher addresses
         */
        while (count--) {
                *(char *)dst = *(char *)src;
                dst = (char *)dst + 1;
                src = (char *)src + 1;
        }
#endif  /* defined (_M_IA64) */

        return(ret);
}


Цитата(ForceKeeper @  6.9.2011,  02:44 Найти цитируемый пост)
Дефолтная функция оказалась в 10-11 раз быстрее.

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


Это сообщение отредактировал(а) volatile - 6.9.2011, 03:00
PM MAIL   Вверх
boostcoder
Дата 6.9.2011, 03:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



пример: http://notes.sochi.org.ru/1322/
в CRT GCC что-то вроде этой. но посложнее.
еще помню, однажды для копирования массивов, нужна была ооочень быстрая memcpy(). я в инетах нашел кучу. но тесты показали, что дефолтная нисколько не медленнее.

Добавлено через 1 минуту и 3 секунды
Цитата(volatile @  6.9.2011,  02:58 Найти цитируемый пост)
        while (count--) {
                *(char *)dst = *(char *)src;
                dst = (char *)dst + 1;
                src = (char *)src + 1;
        }

позор! smile 
PM WWW   Вверх
volatile
Дата 6.9.2011, 03:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(boostcoder @  6.9.2011,  03:03 Найти цитируемый пост)
позор!

Почему позор?
PM MAIL   Вверх
boostcoder
Дата 6.9.2011, 03:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



побайтное копирование! smile

Добавлено через 6 минут и 56 секунд
volatile, посмотри на это? http://lxr.linux.no/linux+v3.0.4/arch/x86/...tring_32.h#L168
выше реализованы использованные в ней функции.

Добавлено через 8 минут и 31 секунду
одна из них в другом файле: http://lxr.linux.no/linux+v3.0.4/arch/x86/lib/mmx_32.c#L28
PM WWW   Вверх
volatile
Дата 6.9.2011, 03:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(boostcoder @  6.9.2011,  03:12 Найти цитируемый пост)
побайтное копирование!

Где-то в старом борланде я видел асмовую memcpy, с копированиями 32-разрядными словами.
Внешне очень красивая. с трюками и развернутыми циклами. щас не могу найти. может завтра..
Но в реале она боюсь окажется не на много быстрее... Это связано с современными процессорами.
Там основное время тратится на не попадание в внутренний кеш процессора.
(страница памяти). И это невелирует различия побайтного и пословного копирования.


Вообще может сравню раельную производительность, если будет время.
PM MAIL   Вверх
boostcoder
Дата 6.9.2011, 03:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



Цитата(volatile @  6.9.2011,  03:27 Найти цитируемый пост)
Там основное время тратится на не попадание в внутренний кеш процессора.

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

Это сообщение отредактировал(а) boostcoder - 6.9.2011, 03:35
PM WWW   Вверх
volatile
Дата 6.9.2011, 03:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(boostcoder @  6.9.2011,  03:33 Найти цитируемый пост)
кеш может на что-то повлиять, если происходит копирование массивов размером меньше линии кеша.


Пример:
1. Побайтое копирование
читаем первый байт, который не находится в кеше. тратим на это 1000 тактов. (грубо)
читаем второй байт (а он уже в кеше) тратим на это 2 такта 
читаем 3 -ий байт тратим  2 такта 
читаем 4 -ый байт тратим  2 такта 
итого 1006 тактов.

2. Теперь читаем словами.
читаем слово, не попадаем в кеш, тратим 1000 тактов.

итого разница между побайтным и пословным копированием 1000 против 1006.

Цифры взял с потолка, просто чтоб объяснить свою мысль.

Цитата(boostcoder @  6.9.2011,  03:33 Найти цитируемый пост)
копирование словами/двойными_словами - всегда быстрее

не спорю. просто возможно что не на много.
Реально может сравню.

PM MAIL   Вверх
boostcoder
Дата 6.9.2011, 03:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



Цитата(volatile @  6.9.2011,  03:45 Найти цитируемый пост)
Пример:
1. Побайтое копирование
читаем первый байт, который не находится в кеше. тратим на это 1000 тактов. (грубо)
читаем второй байт (а он уже в кеше) тратим на это 2 такта 
читаем 3 -ий байт тратим  2 такта 
читаем 4 -ый байт тратим  2 такта 
итого 1006 тактов.

2. Теперь читаем словами.
читаем слово, не попадаем в кеш, тратим 1000 тактов.

итого разница между побайтным и пословным копированием 1000 против 1006.

размер линии кеша - 64 байта.
а теперь посчитай сколько тактов потребуется для копирования массива объемом 128 байт, к примеру ;)
PM WWW   Вверх
Silent
Дата 6.9.2011, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 252
Регистрация: 3.10.2006

Репутация: 1
Всего: 9



Решил проверить, делая ставку на стандартную memcpy:
Код

#include <stdio.h>
#include <memory.h>
#include <Windows.h>
const int N = 70000000;

short mas[N];
short mas2[N];
short * dest = (short*)&mas,
      * source = (short*)&mas2;

void copy1()
{
    memcpy(dest,source,N*sizeof(short));
}

void copy2()
{
    for (int i = 0; i < N; i++)
        dest[i] = source[i];
}

int main()
{
    for (int i = 0; i < N; i++) source[i] = i+1;
    int time = GetTickCount();
    copy1();
    int end = GetTickCount();
    copy2();
    int end2 = GetTickCount();
    printf("Time1: %d\nTime2: %d\n",end-time,end2-end);
    return 0;
}


Результат неожиданный: 
Код

Time1: 79
Tim2: 46


Конфигурация - VS2010, WinXP SP3, i3, 2Gb. Проверил на VS2008 - результат аналогичный.

Посмотрел в ассемблерный листинг - самописанные процедуры в обоих студиях записались так:
Код

    push    esi
    push    edi

; 18   :    for (int i = 0; i < N; i++)
; 19   :        dest[i] = source[i];

    mov    ecx, 35000000                ; 02160ec0H
    mov    esi, OFFSET [email protected]@3PAFA        ; mas2
    mov    edi, OFFSET [email protected]@3PAFA            ; mas
    rep movsd
    pop    edi
    pop    esi

(копирование строки с адреса ds:esi в адрес es:edi)

А вот memcpy - вызов внешней функции:
Код

    push    140000000                ; 08583b00H
    push    OFFSET [email protected]@3PAFA            ; mas2
    push    OFFSET [email protected]@3PAFA            ; mas
    call    _memcpy
    add    esp, 12


Эм... дефолтная функция не умеет использовать процессор на всю катушку?
PM MAIL   Вверх
boostcoder
Дата 6.9.2011, 09:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



volatile же показал код memcpy() используемой в VC2008. чего он нее ожидать-то? smile 
PM WWW   Вверх
Silent
Дата 6.9.2011, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 252
Регистрация: 3.10.2006

Репутация: 1
Всего: 9



ну я не знаю... надеялся на оптимизационные способности компилятора )))
PM MAIL   Вверх
volatile
Дата 6.9.2011, 12:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(Silent @  6.9.2011,  09:38 Найти цитируемый пост)
Time1: 79
Tim2: 46

Ребята, современные процессоры, довольно сложные штуковины.
там 3 уровня кеша.
К тому-же GetTickCount(); слишком груба чтобы сравнивать промежутки времени меньше минуты
у нее слишком большая дискретность.

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


Код

system   = 100%
selfmade = 54%

Просто меняю очередность вызовов местами:
Код

system   = 100%
selfmade = 156%

Функции брал ваши без переделки.
 smile 
PM MAIL   Вверх
Google
  Дата 28.1.2020, 23:47 (ссылка)  





  Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1198 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.