Напомню, в своей предыдущей записи я сделал предположение, что в том конкретном случае 64-битная архитектура проигрывает из-за в 2 раза большего объема обращений к памяти: к куче и к стеку.
На самом деле, проверить, на мой взгляд, достаточно просто. Но, перед тем, как проверять, хочется немного пованговать и проверить, угадаю я или нет.
Проверить мои предположения можно выполнив какой-то алгоритм, который не использует динамическую память и много вызовов процедур. Не особо напрягая голову, я решил, что проще всего это сделать на простейших алгоритмах сортировки. Их преимущество состоит еще и в том, что они очень медленные, поэтому временная оценка будет достаточно точной. Итак, я планирую провести следующие эксперименты:
1. Сортировка простым включением. Проста, как три копейки. Переменных нужно не много, пишется двумя циклами без вызовов процедур. Поэтому вангую, что 32-битный и 64-битный вариант покажут одинаковую скорость работы, +- 5%.
2. Из простых сортировок самая сложная - это шейкерная. Вот где можно развернуться оптимизирующему компилятору с 16 регистрами общего назначения. Вызовов процедур нет. Вангую, что здесь должен победить 64-битный вариант.
3. Ради интереса посмотрим, как работают улучшенные варианты сортировки. Пирамидальная сортировка характеризуется весьма хаотичным обращение к памяти, а также относительной сложностью алгоритма. Вызовов процедур немного. Вангую примерный раритет между платформами.
4. Быстрая сортировка. Достаточно сложный вариант алгоритма, есть где поработать оптимизатору. Но очень много рекурсивных вызовов. Вот тут и можно проверить, влияет ли большое количество регистров, и, соответственно, большое количество операций обращения к памяти стека при вызове процедур, на производительность. Вангую, что 64 бита здесь продуют. Единственная проблема, как сформировать исходные данные так, что бы сортировка выполнялась медленнее всего, а глубина стека была наибольшей.
Интересное Вы исследование затеяли. Я не удержался и, вместо того чтобы слушать лекции по алгоритмам на Курсере, решил реализовать QuickSort на C :) Алгоритм самый простой: средний элемент - опорный, 2 рекурсивных вызова, никаких хитростей. С C я знаком минимально, но надеюсь не облажался покрупному. Сортировал массив из 20М 32-битных случайных чисел (генератор инициирован фиксированным числом, так что массивы всегда одинаковые). Сортировку запускал 10 раз и считал среднее время.
ОтветитьУдалитьКомпилятор: gcc (Ubuntu 4.9.1-16ubuntu6) 4.9.1
Ноутбук довольно старенький: Intel(R) Core(TM)2 Duo CPU T8100 @2.10GHz
Без оптимизации (-O0): 32-bit: 7800 ms, 64-bit: 7939 ms (+2%)
Полная оптимизация (-O2): 32-bit: 4454 ms, 64-bit: 4269 ms (-4%)
Агрессивная оптимизация (-O3): 32-bit: 4429 ms, 4228 ms (-5%)
Другой тест: плохой случай для быстрой сортировки: данные уже отсортированные и алгоритм использует первый элемент в качестве опорного. В данном случае сортировка выполняется за N^2 и сортировать 20М элементов - нереально долго. Поэтому сортируем всего 50К чисел:
Без оптимизации (-O0): 32-bit: 5857 ms, 64-bit: 5989 ms (+2%)
Полная оптимизация (-O2): 32-bit: 2193 ms, 64-bit: 2196 ms (+0%)
Агрессивная оптимизация (-O3): 32-bit: 2127 ms, 2237 ms (+5%)
В общем результаты получились очень близкими, влияние архитектуры если и есть, то минимальное. Что в принципе и понятно: указателей почти нет, алгоритм простой и доп. регистры не пригодились...
Ну что ж, очень интересный результат у тебя получился. Разницы нет совершенно никакой фактически. То есть, судя по твоим результатам, дело в моем тесте было чисто в оптимизаторе, который в Делфи плохо оптимизирует код под 64 бита.
УдалитьЛадно, посмотрим, что получится у меня на Делфи, сравнимым результаты.
Кстати, любопытно, какой код сгенерировался. Чисто для алгоритма, там, наверное, и трех регистров хватит.
Кстати, если перейти к ООП, то там (по крайней мере в Делфи) в вызовах методов еще один регистр компилятор отъедает под self.