Измерение скорости сортировки

Тема в разделе "WASM.A&O", создана пользователем bvcbdbdn125678, 2 июл 2009.

  1. bvcbdbdn125678

    bvcbdbdn125678 Hyduak

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    5
    Адрес:
    Russia
    привет дзенствующим:)

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

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

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    bvcbdbdn125678
    Сами сортировки сравниваются вот здесь
    Сортируется массив из 26 двойных слов, сравнивается количество сравнений
    1) Пузырьковая -- лучший случай — 25, средний — 289, худший — 325
    2) Шейкер -- лучший случай — 25, средний — 259 (лучше пузырьковой сортировки на 20%), худший — 325
    3) Пирамидальная -- средний случай — 109 (лучше пузырьковой сортировки почти в 3 раза)
    4) сортировка прямым включением -- лучший случай — 25, средний — 172 (лучше пузырьковой сортировки на 40%), худший — 325
    Алгоритм можно улучшить пользуясь тем, что готовая последовательность уже упорядочена. Место вставки нового элемента можно найти значительно быстрее, если применить бинарный поиск, исследовав сперва средний элемент упорядоченной последовательности и продолжая деление пополам, пока не будет найдено место вставки. Для n=26 элементов лучший случай — 25, средний и худший — 106 (лучше пузырьковой сортировки почти в 3 раза)
    5) сортировка прямым выбором в худшем, среднем и лучшем случае n*(n-1)/2
    6) сортировка Шелла
    Среднее время работы алгоритма зависит от длин промежутков, на которых будут находится сортируемые элементы исходного списка на каждом шаге алгоритма
    при выборе последовательности значений d1=n/2, d2=d1/2,...,1 в худшем случае алгоритм выполнит O(n2) — сравнений 140
    Table dd 32768,16384,8192,4096,2048,1024,512,256,128,64,32,16,8,4,2,1
    все значения (3^j−1)/2 < n, такая последовательность шагов приводит к алгоритму класса O(n^(3/2)) — сравнений 108
    Table dd 797161,265720,88573,29524,9841,3280,1093,364,121,40,13,4,1
    последовательности вида N=2*N+1 — сравнений 118
    Table dd 32767,16383,8191,4095,2047,1023,511,255,127,63,31,15,7,3,1
    последовательность Дж.Инсерпи и Р.Седгевика — сравнений 115:
    Table dd 198768,86961,33936,13776,4592,1968,861,336,112,48,21,7,3,1
    7) сортировка Хоара (быстрая сортировка)
    Сортировка даёт в среднем O(n log n) сравнений
    По замеру времени под win32 поищи ответы leo на wasm.ru/forum
     
  3. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Квант времени планировщика если ничего не путаю ~20мс, (а если путаю, то сейчас кто-нибудь уточнит ;) соответственно если время работы тестового кода существенно меньше кванта, то вероятность что он будет прерван весьма невелика и такие прерывания будут очень хорошо видны как аномалии при нескольких запусках.
    Поэтому подгоняй время тестирования примерно по 0,1-0,2 времени кванта и будет тебе счастье :). Кроме того можно поднять приоритет потока, тогда кажется до 5с выделяется без прерывания.
    Другое дело, что не забудь учесть, что первое выполнение кода связана с кэшированием и данных и команд (в трэйскеше) и потому время там на порядок больше повторных исполнений. Поэтом выводи несколько, не менее 5х заходов и не удивляйся большой разнице между первым и 3м запусками - какое время "правильное" зависит от того чего ты хочешь получить - для редко исполняемого кода "правильный" первый замер, а для часто исполняемого - типовой после 3-го. И на многоядерниках будет ещё хитрая зависимость от загруженности остальных ядер, где-то тут leo подробности этого эффекта постил, но где не помню.
    Пример профилирования сортировки. и цитата оттуда:
     
  4. bvcbdbdn125678

    bvcbdbdn125678 Hyduak

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    5
    Адрес:
    Russia
    Mikl___
    спасиб за информацию

    Спецификой типов данных я пренебрегаю, н.у. у всех сортировок в моем примере одинаковые.
    Сортируется массив из 100 элементов целого типа без знака.

    Y_Mur
    поднятие приоритета не позволило устранить "помехи" на многопроцессорной системе, увы, почти самое первое что попробовал.
    Пробовалось также Sleep(0).
    Я измеряю скорость сортировки вызовом rdtsc непосредственно перед выполнением основного блока сортировки и вызовом rdtsc после. Соотвественно считаю разницу и получаю кол-во тактов. Некоторой погрешностью на выполнение самого замера тактов так и быть можно пренебречь. Конечный результат для каждой сортировки считается как усредненное значение из N прогонов (где всегда N >= 10).

    Код сортировок на C, при желании можно переписать на asm однако это врядли сильно что-то изменит в конечных результатах.

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

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

    т.е. идеально четкие значение как я понимаю будут получены при выполнении блока кода сортировки без переключения контекста.
    Поправьте если я неправ.

    Любые самые дикие предложения приветствуются:)
    user modом я не ограничен если что:)
     
  5. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Лучше не усреднять N прогонов, а выводить на экран результаты этих N замеров, тогда сразу увидишь и как отличется 1й прогон от типового, и на каком из прогонов возникает "аномалия" из-за переключения контекста. В этом случае "типовое" время увидеть значительно проще чем при усреднении - там одно аномальное значение портит все замеры в серии ;).
    Ну и на многоядернике результаты всегда менее стабильны чем на одноядерном, если эта нестабильность для тебя сильно существенна - отключай "лишние" ядра совсем.
     
  6. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Кстати не забывай про разницу между алгоритмической оптимизацией и оптимизайции при реализации алгоритма ;) Например если один алгоритм работает за n сравнений, а другой за n^2, то сравнивать их скорости при конкретном значении n имхо изначально не корректно ;) Собственно для этого "теоретические" оценки алгоритмов и придуманы, чтобы сравнивать функции от n, а не замеры привязанные к размеру сортируемого массива ;)
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Основные приниципы "борьбы" с виндовыми прерываниями см. например здесь
    Плюс к этому не мешает проверить величину системного кванта (тика) времени, т.к. мультимедийные службы могут уменьшать его до 1 мс (timeBeginPeriod), что ес-но негативно сказывается на всем остальном из-за слишком частого переключения потоков.
    Что касается многопроцессорности, то
    1) С HyperThreading'ом бороться бесполезно - его нужно просто отрубать в биосе на время измерений
    2) Работа с большими объемами памяти сама по себе нестабильна, а в многоядерных процах тем более. Поэтому для повышения точности сравнительных тестов лучше брать небольшие объемы и предварительно загружать данные в кэш. Если же нужна проверка работы именно с учетом подкачки данных из ОЗУ, то повышенный разброс неизбежен, а "дурное" влияние других ядер можно уменьшить, загрузив их своими потоками "пустышками", не обращаюшимися к памяти (крутить, какой-нить, fdiv в цикле) - ну и на всякий сл. задать всем потокам привязку к процессорам
     
  8. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    А помойму виндовые прерывания и перепланирование это бред. Сколько их тестировал не замечал. Либы они уходили как средее либы были не успевали случиться.

    Зато вот кэш порой ускаряет обработку 1.5 раза.


    Дело в том что 10 недостаточно. 10 дает ошибку 10-50%. Для измерений рекомендуют более >30
    Но меня это неустраивает лучше 50-100 тогда ошибка будет 1-5%.
    Когда время инструкций мерил брал 1000 и больше ошибка 1/1000, но тут проблемы что планировщик уже начинает мешать. Зато крассивые результаты (1.00x 0.33x)

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