Перейти к содержимому

Небольшое ускорение

Я уже публиковал несколько модификаций для некоторых функций из libc, оптимизированных для быстрой работы на современных процессорах (см. категорию Algorithms and Technologies).

Все эти функции были реализованы в поисковом движке DataparkSearch Engine. Поскольку производительность этих функций, особенно в сравнении со стандартной реализацией на конкретной платформе, зависит от используемых микропроцессора и уровня оптимизации компилятора, я добавил специальную процедуру тестирования на этапе конфигурирования DataparkSearch, выбирающую только те новые варианты функций, которые исполняются быстрее на платформе, где производится установка. Это позволяет получить максимальную производительность DataparkSearch на каждой платформе.

Также я выделил эти функции в отдельную библиотеку, libdp, которая может быть установлена на ваш ПК отдельно и использоваться для ускорения любой динамически слинкованной программы (через переменную окрежения LD_PRELOAD). Например:


LD_PRELOAD=/usr/local/dpsearch/lib/libdp-4.so perl programm.pl

Сравнение теста производительности PerlBench для интерпретатора Perl, запускаемого на процессоре Intel Celeron M под управлением ОС Ubuntu Linux 10.04. Конфигурция A запускает системный интерпретатор Perl как /usr/bin/perl, конфигурация B запускает тот же интерпретатор как /usr/bin/perl5.10.1, конфигурация C запускает системный Perl с библиотекой libdp, предварительно загруженной при помощи переменной окружения LD_PRELOAD. Небольшие отличия в производительности в пределах 1-2% могут рассматриваться как случайные флуктуации, а соответствующие тесты выполняемыми с одинаковой производительностью.

Сравнение теста производительности rjsh-pybench для системного интерпретатора Python, запускаемого на том же ноутбуке без (benchmark p0) и с (benchmark p1) предварительно загруженной библиотекой libdp.


PYBENCH 1.4

Benchmark: p1 (rounds=20, warp=1)

Comparing with: p0 (rounds=20, warp=1)
Tests:                              min run     cmp run     avg run      diff
-----------------------------------------------------------------------------
          BuiltinFunctionCalls:   169.50 ms   159.50 ms   173.80 ms    +6.27%
           BuiltinMethodLookup:   179.00 ms   179.00 ms   190.12 ms    -0.00%
                 CompareFloats:   289.00 ms   289.00 ms   300.25 ms    +0.00%
         CompareFloatsIntegers:   239.00 ms   219.50 ms   245.63 ms    +8.88%
               CompareIntegers:   219.00 ms   218.50 ms   228.90 ms    +0.23%
        CompareInternedStrings:   217.00 ms   217.00 ms   226.40 ms    +0.00%
                  CompareLongs:   209.00 ms   208.50 ms   213.35 ms    +0.24%
                CompareStrings:   277.50 ms   277.50 ms   285.00 ms    +0.00%
                CompareUnicode:   218.50 ms   218.50 ms   223.83 ms    +0.00%
                 ConcatStrings:   139.50 ms   159.50 ms   156.62 ms   -12.54%
                 ConcatUnicode:   169.50 ms   189.50 ms   185.28 ms   -10.55%
               CreateInstances:   189.00 ms   189.00 ms   193.50 ms    +0.00%
            CreateNewInstances:  1117.00 ms  1127.00 ms  1141.15 ms    -0.89%
       CreateStringsWithConcat:   198.50 ms   208.50 ms   201.85 ms    -4.80%
       CreateUnicodeWithConcat:   179.50 ms   209.50 ms   196.13 ms   -14.32%
                  DictCreation:   179.00 ms   179.00 ms   186.83 ms    +0.00%
             DictWithFloatKeys:   199.00 ms   199.00 ms   206.60 ms    -0.00%
           DictWithIntegerKeys:   218.00 ms   218.00 ms   224.75 ms    +0.00%
            DictWithStringKeys:   317.00 ms   317.00 ms   326.80 ms    +0.00%
                      ForLoops:   179.50 ms   189.50 ms   195.80 ms    -5.28%
                    IfThenElse:   258.00 ms   258.00 ms   271.63 ms    +0.00%
                   ListSlicing:   289.00 ms   289.00 ms   297.30 ms    +0.00%
                NestedForLoops:   449.50 ms   449.50 ms   467.98 ms    +0.00%
          NormalClassAttribute:   248.00 ms   249.00 ms   254.55 ms    -0.40%
       NormalInstanceAttribute:   248.50 ms   248.50 ms   253.50 ms    +0.00%
           PythonFunctionCalls:   289.00 ms   289.00 ms   294.23 ms    -0.00%
             PythonMethodCalls:   279.50 ms   279.50 ms   291.72 ms    +0.00%
                     Recursion:   179.50 ms   179.50 ms   192.52 ms    +0.00%
                  SecondImport:   868.00 ms   888.50 ms   884.02 ms    -2.31%
           SecondPackageImport:   119.50 ms   119.50 ms   127.45 ms    +0.00%
         SecondSubmoduleImport:   129.50 ms   129.50 ms   138.88 ms    +0.00%
       SimpleComplexArithmetic:   189.50 ms   199.00 ms   203.45 ms    -4.77%
        SimpleDictManipulation:   308.50 ms   308.50 ms   322.00 ms    +0.00%
         SimpleFloatArithmetic:   348.00 ms   348.50 ms   358.18 ms    -0.14%
      SimpleIntFloatArithmetic:   268.00 ms   268.00 ms   277.42 ms    +0.00%
       SimpleIntegerArithmetic:   188.50 ms   188.50 ms   195.37 ms    +0.00%
        SimpleListManipulation:   268.50 ms   258.50 ms   275.75 ms    +3.87%
          SimpleLongArithmetic:   189.50 ms   179.00 ms   198.60 ms    +5.87%
                    SmallLists:   148.50 ms   148.50 ms   153.90 ms    -0.00%
                   SmallTuples:   179.00 ms   169.50 ms   183.95 ms    +5.60%
         SpecialClassAttribute:   199.00 ms   199.00 ms   202.32 ms    +0.00%
      SpecialInstanceAttribute:   279.00 ms   279.00 ms   285.30 ms    -0.00%
                StringMappings:   259.00 ms   259.00 ms   266.23 ms    -0.00%
              StringPredicates:   235.50 ms   235.50 ms   246.42 ms    -0.00%
                 StringSlicing:   128.50 ms   139.00 ms   138.25 ms    -7.55%
                     TryExcept:   198.00 ms   198.50 ms   202.45 ms    -0.25%
                TryRaiseExcept:   129.00 ms   129.00 ms   135.25 ms    +0.00%
                  TupleSlicing:   289.50 ms   299.00 ms   305.12 ms    -3.18%
               UnicodeMappings:   229.00 ms   239.00 ms   247.88 ms    -4.18%
             UnicodePredicates:   244.50 ms   244.50 ms   253.53 ms    -0.00%
             UnicodeProperties:   186.50 ms   186.00 ms   194.32 ms    +0.27%
                UnicodeSlicing:   109.50 ms   129.00 ms   122.97 ms   -15.12%
-----------------------------------------------------------------------------
   Notional minimum round time: 13036.00 ms 13156.50 ms                -0.92%

Различия в менее, чем 1% могут также рассматриваться как случайные флуктуации.

Небольшое ускорение: 11 комментариев

  1. Уведомление: Tweets that mention Небольшое ускорение -- Topsy.com

  2. Itman

    Ok, увидел кое-что. То есть речь идет исключить о cycle unfolding, или что-то еще используется для ускорения?

  3. Maxime

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

  4. Itman

    Возможности pipeline на уровне развертывания цикла или что-то большее?

  5. Maxime

    Да, в основном развертывание циклов. А что там может быть большее, есть какие либо примеры под рукой?

  6. Itman

    Вот это я и хотел узнать. Еще можно, конечно, использовать SSE инструкции, но будет работать только под Intel и AMD64

  7. Maxime

    Кстати, я добавил тестирование реализаций при конфигурировании, на 64-битном AMD процессоре под Debian никакого ускорения не получается, а вот на Intel Celeron M или на том же AMD64, но под FreeBSD, получается быстрее.
    Возможно у Debian есть ассемблерная реализация функций libc (может и не всех), которая линкуется, если выбрана опция -O2 или -O3.

  8. Itman

    Многие intrinsics заменяются на специальные эффективные команды процессора. Плюс на новых моделях процессорах, выравнивание по границе слова не увеличивает скорость доступа.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *