⇣ Содержание
Опрос
|
реклама
Самое интересное в новостях
Прямое сравнение производительности КПК и настольных систем
Автор: Стас Вихров
ПримечаниеЛично я, других исследований на тему сравнения производительности архитектур StrongARM и х86 не нашел, поэтому пришлось придумать собственную методику и написать тестовое приложение. Соответственно не обошлось без нескольких спорных моментов. Это ведь не очередной обзор коврика для мыши или тестирование мягкости нажатия кнопок мобильного телефона. Самый спорный момент в данной статье - отказ от оптимизации кода. Остановлюсь на этом моменте подробнее. Архитектуры х86 и StrongARM несовместимы на уровне машинного кода, соответственно мы вынуждены воспользоваться разными компиляторами. А разные компиляторы и оптимизируют по-разному. Одни "сообразительнее", другие менее сообразительные. Соответственно, возможна ситуация, когда более слабый процессор покажет лучшие результаты, чем более быстрый, за счет более сообразительного компилятора. А нас интересует сравнение именно самих процессоров. В принципе, можно было бы сделать данный тест и единым, если бы мы его написали на C#. Тогда бы, один и тот же exe-шник можно было бы запускать и на x86-х машинах, и на StrongARM. Но тогда мы, стали бы заложниками эффективности реализации .NET Framework на соответствующей платформе. А мне хотелось максимально контролировать получаемый код и быть как можно независимее от ОС, компилятора, версии .NET Framework и т.д - то есть всего, что не связано с железом. Естественно, это неосуществимо. Но снизить влияние других факторов вполне можно. Несколько слов об оптимизацииОптимизацию можно условно разделить на 3 вида: 1.Оптимизация машинного кода. Дело в том, что одну и ту же программу, написанную на языке высокого уровня, в данном случае на С, перевести в машинный код можно множеством способов. Вот простой пример. Допустим нам нужно поместить в регистр AX - ноль. Это можно сделать следующими способами:
Один из этих способов окажется быстрее. Причем, какой именно, зависит от конкретного процессора. Одни процессоры лучше работают с длинными командами, другие с короткими и т.д. А если бы мы выбрали оптимизацию на минимальный размер, то возможно выбрался бы какой-нибудь другой способ. Естественно, в реальных приложениях все много сложнее, т.к скорость выполнения зависит и от окружающих команд. Так же очень сильно на скорость выполнения влияет порядок команд (ведь часто от смены порядка нескольких соседних команд суть кода не меняется). 2. Использование специфических особенностей процессора. Это, прежде всего, расширенные наборы команд MMX, SSE1-3 и другие (конкуренты Intel тоже не отстают в командотворчестве). Эти команды хороши, но не всесильны. Область их эффективного применения довольно ограничена. Их суть ясна из их общего названия - SIMD (Single Instruction - Multiple Data/Одна инструкция - Много данных). Другими словами, они позволяют выполнить за одну команду какое-либо действие сразу же над несколькими числами. Это достигается за счет того, что данные наборы команд работают со специальными длинными регистрами, в которые можно поместить целый набор чисел - до 16-ти. MMX предназначен для обработки целых чисел и использует регистры сопроцессора (только 64 бита), в то время, как SSE работает с вещественными числами и использует собственные 128-битные регистры. SSE2, SSE3 развивают идеи заложенные в MMX и SSE. Таким образом, данные команды хорошо подходят для алгоритмов, которые выполняют простые, однотипные действия над большим объемом данных. Причем, эти алгоритмы должны иметь поменьше условных переходов, а вычисления можно было бы "распараллелить" (т.е для каждого последующего вычисления не нужно было бы знать результат предыдущего). В качестве примеров таких задач можно привести MPEG-декомпрессию, шифрование, преобразование цветового пространства, наложение текстуры, работу с комплексными числами, быстрое преобразование Фурье, дискретное косинус-преобразование, обсчет 3-х мерных сцен. Это весьма ресурсоемкие задачи, которые постоянно встречаются при работе с мультимедийными данными и играми. Поэтому понятно, почему инженеры Intel ввели в архитектуру процессора механизмы ускорения подобных задач - имеет смысл ускорять то, что выполняется дольше всего. Задачи из моего тестового приложения очень плохо подходят для данного вида оптимизации. В них сплошные условные переходы, размерности массивов задаются переменными, вычисления не распараллеливаются, используются тригонометричекие функции. 3.Оптимизация алгоритма. Его суть заключается в замене одного алгоритма, другим, более быстрым (или более коротким, если выбрана оптимизация на размер), но который делает тоже самое. Тоже небольшой пример. Пусть есть программа: int a = 1; for (int i = 0; i < 3; i++) a += i*a; она может быть оптимизирована, например, следующим образом: int a = 1; a+= 0*a; a+= 1*a; a+= 2*a; очевидно второй вариант будет сильно быстрее (этот метод оптимизации называется "развертывание цикла"). А более умный компилятор может вообще заменить эту программку одной строчкой: int a = 6 или вот еще пример: int i, j, a = 0; for (i = 0; i < 10; i++) { for (j =0; j < 10; j++) { a += (i*15 + j*20); } } можно оптимизировать, например, так: int i, j, k, a = 0; for (i = 0; i < 10; i++) { k = i*15; for (j =0; j < 10; j++) { a += (k + j*20); } } в первом случае имеем 200 операций умножения, во втором всего 110. Соответственно второй вариант сильно быстрее. (Этот метод оптимизации называется "вынос константы из цикла"). Оптимизация алгоритма - потенциально самый эффективный, но сложно реализуемый способ. Тем не менее, компиляторы пишут не один десяток лет и те примеры оптимизаций, которые я привел и даже на порядки более сложные, вполне реальны для современных средств разработки. Именно что бы исключить влияние последнего вида оптимизации, я ее и отключил. Мне нужно было, что бы каждый процессор выполнил один и тот же объем вычислений на одном и том же алгоритме. Меня не устраивала ситуация, когда на одной архитектуре, благодаря хорошей оптимизации, могло выполняться в 2 раза меньше вычислений, чем на ее "сопернице". Собственно, это основное требование при проведении любых тестов - нужно что бы выполнялось строго одинаковое задание. Если бы я сравнивал не исключительно процессора, а платформу в целом, включая все приемущества и недостатки, то тогда, возможно, имело бы смысл оптимизацию и включить. Ведь существование хорошо оптимизирующего компилятора - большое приемущество платформы. Но я сравнивал только процессора и мне нужно было поставить их в одинаковые условия. К тому же, если бы я в своих расчетах использовал оптимизированную версию тестового приложения, то сразу же возникла бы масса вопросов: какие ключи оптимизации использовать, а какие нет? Что делать если с одними ключами оптимизации одна задача работает быстрее, а другая медленнее, относительно другого набора ключей? Почему выбран именно этот компилятор и эта ОС? Какой вариант теста использовать, если один компилятор лучше оптимизирует одни задачи, а другой компилятор - другие? Какой компилятор использовать, если один лучше оптимизирует архитектуру PentiumIII, а другой Pentium4? К сожалению, перепробовать все компиляторы со всеми ключами оптимизации, на всех ОС у меня не было возможности. А при выключенной оптимизации все компиляторы переводят программу в машинный код более-менее одинаково. Да и компиляторы я выбрал похожие и от одного производителя. Эти 2 компилятора, несмотря на свой возраст (особенно Visual Studio 6.0 - он был выпущен в 1998г; eMbedded Visual C++ 4.0 - 2004г.), до сих пор очень широко используются программистами. VC++ 6.0 стал своего рода классикой - он быстрый, компактный, с удобным интерфейсом. В нем есть все что нужно; многие С++ программисты просто не видят смысла переходить на что-либо другое. Если бы мы выбрали другие компиляторы, то вероятно, разброс результатов был бы немного другой, но общая картина осталось бы прежней. Для эксперимента я скомпилировал данный тест в появившемся всего лишь несколько недель назад и широко рекламируемом пакете разработки Visual Studio 2005. К счастью, он "съел" проект без малейшей модификации. Естественно, параметры компиляции я установил такими же. Вот результаты для компьютера с процессором PentiumIII 866:
Как видите, на новейшем компиляторе и компиляторе выпущенном уже 7 лет назад, код, в плане быстродействия, получился практически одинаковым! Конечно, по одному этому примеру еще ни о чем судить нельзя. Вообще, данная статья имеет и некоторый философский смысл - она наглядно демонстрирует невозможность полностью объективного сравнения. Любая методика тестирования неизбежно накладывает ограничения. Особенно это касается сравнений различных платформ. Понятие производительности многомерное и его нельзя однозначно спроецировать на плоскую шкалу. Пространство вычислительной мощности системы состоит из множества измерений (осей), в том числе из следующих:
Увеличение производительности по одному измерению не всегда ведет к увеличению по другим измерениям. Таким образом, скорость системы можно представить в виде N-мерной фигуры, но ни как не в виде одномерного отрезка. Для 2-х процессоров практически никогда нельзя сказать, что один быстрее другого на столько-то процентов. Даже если процессора на одном ядре, у них может быть разная внутренняя частота, разный коэффициент умножения, разный размер кэша - все эти параметры влияют на размерности "фигуры производительности" по-разному. По многочисленных просьбам приведу таблицу, которую я получил, включив в компиляторах оптимизацию (пресет Maximize Speed). Только замечу, что учитывая все вышесказанное, эта таблица не имеет никакого особого практического смысла. Разве только подтверждает моё предположение, что на StrongARM есть больше возможностей для оптимизации.
Строка "Ratio" - ускорение работы после оптимизации. Жирным выделен лучший результат. Как видим, эффект от оптимизации оказался весьма значителен. В большинстве случаев PXA показал более сильное ускорение работы. Но все-равно, до х86 еще далеко. Забавный момент - после включения оптимизации тест "Prime" на PIII стал работать даже медленнее - такие "баги" иногда случаются. Ну и "нормированные" значения:
Если Вы заметили ошибку — выделите ее мышью и нажмите CTRL+ENTER.
|