Замер производительности

Я уже как-то говорил, что хочу посмотреть насколько скомпиленное в .NET работает быстрее, чем скомпиленное или интерпретированное в старых добрых системах. Собственно я написал версию для Python и С. Немного изменил способ замера времени в IronPython.

Мы с Андреем решили использовать простой алгоритм решета Эратосфена. В функцию передается n, функция возвращает нам массив простых чиселАлгоритм на питоне выглядит так:

def Eratosfen(n):
array = [0, 1]
for i in range(2, n + 1):
array.append(i)
for i in range(2, n + 1):
for x in range(1,n / i):
array[i * x] = -1
if i * i>=n:
return array

На С все тоже самое только под массив, естественно, сразу выделяется небходимая память.
Сишный код:

#include «stdafx.h»
#include «time.h»
char* eratosfen(int n){
char *arr;
arr = new char[n+1];
for(int i = 1; i< n + 1; i++)
arr[i] = i;
for(int i = 2; i < n + 1; i++){
for(int x = 1; x < n / i; x++)
arr[i * x] = -1;
if (i * i>=n)
return arr;
}
}
Вобщем, вот что получилось, при n = 1 000 000:

.NET C 3.5: 0.016000
GCC 3.1: 0.109000
Python 2.5.1: 1.888526
IronPython 1.1: 7.734375 (!)

От железного змея я такого не ожидал. Уступить интерпретируемуму питону очти в 7 раз! Причину надлежит установить. Буду надеяться, что во всем виновата моя криворукость.

Реклама

Замер производительности: 8 комментариев

  1. Выложи код всех вариантов.
    Меня не только айронпитон удивил, но и Си. Дотнет ну никак не может работать быстрее нативного кода.
    Особенно с учетом того, что моя версия на шарпе была написана с минимальной оптимизацией(использование медленных списков и тому подобное).

    На айроне тоже используется массив с изменяемой длинной как в обычном питоне? Тогда это объясняет — тормоза возможны при его инициализации.

  2. у меня есть подозрение, что массив там реализован как List

    и как со всеми односвязными списками доступ к элементу по индексу занимает охренительное время (надо ж с вершины перебрать i элементов по порядку).

    Вот отсюда и тормоза ;)

  3. Вот такая функция для Си:

    char* eratosphen(int n)
    {
    char *arr = malloc(sizeof(int) * n);
    int i, j;
    for (i = 0; i < n; i++)
    arr[i] = 0;
    for (i = 2; i < n; i++)
    if (0 == arr[i])
    for (j = i + i; j < n; j += i)
    arr[i] = -1;
    return arr;
    }

    На моем компе для n = 1 000 000 работает меньше миллисекунды,
    для n = 100 000 000 — 0.312 секунды.

    Для аналогичного алгоритма на шарпе(несколько более тормозного из-за использования списка для хранения списка простых чисел):
    n = 1 000 000 — 0.026 секунд.
    n = 100 000 000 — 9.056 секунд.

    Разница видна невооруженным глазом ;)
    В твоем варианте просто слишком много умножений без которых
    можно обойтись вообще.

  4. Ой…. Это я выше писал ;)
    Забыл дописать, что скомпилено все на VC++ 2008

  5. бррр…. короче оно такое:

    char* eratosphen(long n)
    {
    char *arr = malloc(sizeof(char) * n);
    long i, j;
    for (i = 0; i < n; i++)
    arr[i] = 0;
    for (i = 2; i < n; i++)
    if (0 == arr[i])
    for (j = i + i; j < n; j += i)
    arr[i] = -1;
    return arr;
    }

  6. нуу… вобщето массив в питоне это и есть list ;)
    есть еще tuple — кортеж по-русски — вполне вероятно, что в железном змее предпочтительней использовать именно его. хотя в обычном питоне таких проблем вроде нет…

    вобщем, да. си-шарп предпочтительней;)

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

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s