LINUX.ORG.RU

Функциональная языкометрия

 расчет факториала


2

3

Поскольку, как всем известно, основное предназначение различных функциональных ЯП состоит в расчете факториалов, давайте померяемся - какой ЯП это делает быстрее (при условии что делает правильно)? Естественно имеет значение машина на которой идет счет.

Условия такие - надо посчитать 10000! и вывести его в 16ти-ричном виде (буквочки маленькие), без всяких '0x' вначале и какой то служебной лабуды в конце. Что бы не постить прстыни, для контроля правильности ответа предлагается использовать md5sum. Вот как это выглядит на втором питоне:

$ python -c 'print hex(reduce( long.__mul__, range(1,10000+1), 1L ))[2:-1]' | md5sum
3de6339590fbdf0a1c0ae2f2b820f8bf  -

Вот однострочник, выводящий модель проца, частоту и время работы (я привожу несколько примеров для доступных мне машин):

$ ssh host1 "less /proc/cpuinfo | grep 'model' | tail -n 1; less /proc/cpuinfo | grep 'cpu MHz' | tail -n 1; time python -c 'print hex(reduce( long.__mul__, range(1,10000+1), 1L ))[2:-1]' | md5sum"
model name      : AMD FX(tm)-8320 Eight-Core Processor           
cpu MHz         : 1400.000
3de6339590fbdf0a1c0ae2f2b820f8bf  -

real    0m0.058s
user    0m0.048s
sys     0m0.008s

-------------------------------------------------
model name      : Intel(R) Core(TM)2 CPU         U7500  @ 1.06GHz
cpu MHz         : 798.000
3de6339590fbdf0a1c0ae2f2b820f8bf  -

real    0m0.301s
user    0m0.256s
sys     0m0.024s

--------------------------------------------------
model name      : Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz
cpu MHz         : 1600.000
3de6339590fbdf0a1c0ae2f2b820f8bf  -

real    0m0.042s
user    0m0.040s
sys     0m0.000s

--------------------------------------------------
model name      : AMD Phenom(tm) 9550 Quad-Core Processor
cpu MHz         : 1100.000
3de6339590fbdf0a1c0ae2f2b820f8bf  -

real    0m0.083s
user    0m0.068s
sys     0m0.012s

---------------------------------------------------
model name      : AMD Phenom(tm) 9850 Quad-Core Processor
cpu MHz         : 2506.801
3de6339590fbdf0a1c0ae2f2b820f8bf  -

real    0m0.123s
user    0m0.118s
sys     0m0.004s

----------------------------------------------------
model name      : Intel(R) Core(TM)2 Quad  CPU   Q9450  @ 2.66GHz
cpu MHz         : 2506.801
3de6339590fbdf0a1c0ae2f2b820f8bf  -

real    0m0.124s
user    0m0.118s
sys     0m0.006s

----------------------------------------------------
model name      : AMD Opteron(tm) Processor 6174
cpu MHz         : 2506.801
3de6339590fbdf0a1c0ae2f2b820f8bf  -

real    0m0.120s
user    0m0.119s
sys     0m0.002s

----------------------------------------------------
model name      : Intel(R) Xeon(R) CPU           X5670  @ 2.93GHz
cpu MHz         : 1600.000
3de6339590fbdf0a1c0ae2f2b820f8bf  -

real    0m0.120s
user    0m0.060s
sys     0m0.004s

Я к чему предлагаю померяться - только что обнаружил в соседнем треде, что вечный-тормоз-питон в таком тесте на порядок(!) обогнал священную-корову-лисп;-)))

Предлагайте свои решения на других ЯП (хаскель очень интересен;-))

★★★★★

Достану свой.

Ноут EMashines.

> less /proc/cpuinfo | grep 'model' | tail -n 1; less /proc/cpuinfo | grep 'cpu MHz' | tail -n 1; time perl -MDigest::MD5 -MMath::Combinatorics -e'print Digest::MD5->md5_hex(factorial(10000));'
model name      : Pentium(R) Dual-Core CPU       T4500  @ 2.30GHz
cpu MHz         : 2300.000
3c9b0f15175cf7bf02198ffa31871e50
real    0m0.044s
user    0m0.039s
sys     0m0.005s

Да, про md5sum забыл. Вот

> less /proc/cpuinfo | grep 'model' | tail -n 1; less /proc/cpuinfo | grep 'cpu MHz' | tail -n 1; time perl -MDigest::MD5 -MMath::Combinatorics -e'print Digest::MD5->md5_hex(factorial(10000));' | md5sum
model name      : Pentium(R) Dual-Core CPU       T4500  @ 2.30GHz
cpu MHz         : 2300.000
59acb3d957d1908c42d26d61ffd6f043  -

real    0m0.046s
user    0m0.039s
sys     0m0.007s

UPD:

И на сервачке

> ssh bvn13@192.168.13.13 "less /proc/cpuinfo | grep 'model' | tail -n 1; less /proc/cpuinfo | grep 'cpu MHz' | tail -n 1; time perl -MDigest::MD5 -MMath::Combinatorics -e'print Digest::MD5->md5_hex(factorial(10000));' | md5sum"
Password:
model name      : Intel(R) Pentium(R) 4 CPU 2.80GHz
cpu MHz         : 2813.348
59acb3d957d1908c42d26d61ffd6f043  -

real    0m0.069s
user    0m0.052s
sys     0m0.008s

bvn13 ★★★★★
()
Последнее исправление: bvn13 (всего исправлений: 2)

это тест чего, работы IO и конкатенации строк? все варианты в system половину времени проводят. Вариант на String-с у меня немного проиграл питону, зато я обнаружил баг, спасибо.

qnikst ★★★★★
()

Тестирование сишных функций, которые дергаются из питона, - это, конечно, хорошо. Но где здесь собственно сам питон, кроме reduce и range, которые по идее должны отрабатывать моментально на n=10000?

Кстати, похожие фаллометрические тесты уже были на ЛОРе. Оказалось, что там тоже «измеряли» скорость сишных библиотек по работе с длинными целыми. Но зато как было подано! Да, забывается...

dave ★★★★★
()
Последнее исправление: dave (всего исправлений: 1)
Ответ на: комментарий от dave

не не не.. ТС молодец, благодаря нему бы баг в text нашли :) а так да, сравнение скорости байндингов к gmp и самой gmp + IO, если в питоне и hex не питоний, а сишный, то языка там нет совсем.

qnikst ★★★★★
()

из предыдущего треда:

racket:

> (time (factorial 100000) 0)
cpu time: 984 real time: 1001 gc time: 62
0
> 
python:
>>> timeit.timeit('import math; math.factorial(100000)', number=1)
34.108616597919536
ну и хешсумму смысла считать нет, лучше натуральный логарифм какой-нибудь.

anonymous
()
Ответ на: комментарий от ymn

а много ли вариантов решения по этой сслыке могут посчитать 10000!? А хде замеры производительности? За что благодарить то?

AIv ★★★★★
() автор топика
Ответ на: комментарий от anonymous

факториал энто неспортивно. Я тож могу забиндить в питон специальный Сшный факториал:-) Ручками, ручками, через алгебраические операции.

AIv ★★★★★
() автор топика
Ответ на: комментарий от qnikst

ну считайте 100 000! что бы от ИО отстроится как то. Всем противникам С-ф-й и ъ-ЯП - много есть ЯП у которых операция * в итоге не дернет фрагмент С-шного когда? Вы ище против ассемблера попротестуйте.

AIv ★★★★★
() автор топика
Ответ на: комментарий от anonymous

нет. Я забиндил умножение. Кто не биндит умножение? Я подозреваю что даже вижуал бейсик биндит сишное умножение;-)

AIv ★★★★★
() автор топика

так да. Но я не оч понимаю откуда такая шустрота, длинные целые что ли хошо сделаны?

Там много чего хорошо сделано. Я не понимаю как вы без нее обходитесь, если работаете с расчетами.

PS: это я аноном за математику писал в соседнем треде. Отвечаю сюда, а то там какая то полезная дискуссия идет.

ebantrop
()
Ответ на: комментарий от AIv

умножение = тасование битов руками? у тебя какое-то превратное представление о сишном умножении и FFI. Ну и в хацкелях можно биты и raw память руками тасовать.

qnikst ★★★★★
()
Ответ на: комментарий от AIv

у нас не те расчеты. На наших расчетах она сдохнет.

Да на ней вообще не надо считать, а удобно генерить код. Если что не сложное, типа факториальной языкометрии, то тогда да, можно и посчитать. Работает как видно шустро, время это было на мобильном i7 @ 2,66 GHz.

ebantrop
()
Ответ на: комментарий от AIv

Я забиндил умножение.

Ну то есть ту функцию, в которой поток исполнения проводит 99% времени.В чем отличие от того, чтобы забиндить весь факториал, не могу понять? Все равно же питон ничего не делает в данном случае.

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

anonymous
()
Ответ на: комментарий от qnikst

питон написан на С. Ява написана на С. Поэтому крики о том что была забиндена С_шная ф-я улыбают - любой пук на питоне это обращение к С.

На чем перл написан? И т.д. Это значит, что в исходниках ЯП где то есть кусок кода (на С) в котром происходит умножение. Канешно, есть наверное ЯП которые размещают данные в регистрах, вызывает соотв интрукцию, забирают данные из регистра...и много таких (функциональных)?

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

питон написан на С

Не любой.

Ява написана на С.

Ява, внезапно, написана на яве.

ЗЫ. За «сишное умножение» большое спасибо.

staseg ★★★★★
()
Ответ на: комментарий от AIv

питон написан на С. Ява написана на С. Поэтому крики о том что была забиндена С_шная ф-я улыбают - любой пук на питоне это обращение к С.

извини, но такой бредятины^W демагогии я дано не читал.. искренне надеюсь, что ты ещё не преподаешь студентам. Ты серьезно не понимаешь разницу между умножением «нативных для ЯП» чисел делаемым рантаймом ЯП и вызовом функций библиотеки gmp, и серьёзно не знаешь как это работает?

P.S. в задаче основные тормоза в hex, но я уже боюсь тебя спрашивать знаешь ли ты как она реализована в питоне?

qnikst ★★★★★
()

насчёт формата вывода, а буковки в шестнадцатеричном выхлопе большие или маленькие должны быть? А то что-то результат не сходится

Harald ★★★★★
()
Ответ на: комментарий от AIv

питон написан на С. Ява написана на С. Поэтому крики о том что была забиндена С_шная ф-я улыбают - любой пук на питоне это обращение к С.

На чем перл написан? И т.д. Это значит, что в исходниках ЯП где то есть кусок кода (на С) в котром происходит умножение. Канешно, есть наверное ЯП которые размещают данные в регистрах, вызывает соотв интрукцию, забирают данные из регистра...и много таких (функциональных)?

Решил отобрать у drBatty лавры главного поставщика бреда в Development?

encyrtid ★★★★★
()
Ответ на: комментарий от Harald

ввотт, эталонное сишное умножение, любуйтесь :)

less /proc/cpuinfo | grep 'model' | tail -n 1; less /proc/cpuinfo | grep 'cpu MHz' | tail -n 1; time ./fact 10000 | tr '[A-Z]' '[a-z]' | md5sum
model name      : Intel(R) Core(TM) i3-2330M CPU @ 2.20GHz
cpu MHz         : 2200.000
3de6339590fbdf0a1c0ae2f2b820f8bf  -

real    0m0.025s
user    0m0.024s
sys     0m0.002s

#include <openssl/bn.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv)
{

if (argc > 1)
{
BIGNUM *n, *r;
BN_CTX *ctx;

n = BN_new();
ctx = BN_CTX_new();

BN_set_word(n, atol(argv[1]));

r = BN_dup(n);

while(!BN_is_one(n))
{
BN_sub_word(n, 1);
BN_mul(r, r, n, ctx);
}

puts(BN_bn2hex(r) + 1);

}

return 0;
}
Harald ★★★★★
()
Ответ на: комментарий от Harald

кстати, то же самое, скомпилированное под 32 бита тормозит больше чем в два раза:

model name      : Intel(R) Core(TM) i3-2330M CPU @ 2.20GHz
cpu MHz         : 2200.000
3de6339590fbdf0a1c0ae2f2b820f8bf  -

real    0m0.056s
user    0m0.052s
sys     0m0.006s
Harald ★★★★★
()
Последнее исправление: Harald (всего исправлений: 1)
def powl(a,n):
    r=1;
    while(n>0):
        if(n%2==1):r*=a;
        a*=a;
        n/=2;
    return r;

def prime(n):
    a=range(n+2)
    o=[]
    for x in range(2,n+1):
        if(a[x]==1):continue
        t=n;k=0;
        while t>0:
            t=t/x
            k+=t
        o.append(powl(x,k))
        y=x;
        while y<n+1:
            a[y]=1
            y+=x
    return o
def fac(n):
    return prime(n)
    o=[]
    for x in prime(n):
        t=n;k=0;
        while t>0:
            t=t/x
            k+=t
        o.append(powl(x,k))
    return o

def ffac(n):
    return hex(reduce(long.__mul__,fac(n),1L))

print ffac(10000)[2:-1] 

для 10000 на четверть меньше real чем твой однострочник.
для 100000 в два раза быстрее твоего ( на моём real 2.659s vs 5.631s)
для 1000000 всё ещё думает мой - твой и проверять видимо не буду :)

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

для 1000000 моё

less /proc/cpuinfo|grep 'model' |tail -n 1;less /proc/cpuinfo|grep 'cpu MHz'|tail -n 1; time python fa.py|md5sum
model name	: AMD Athlon(tm) II X2 220 Processor
cpu MHz		: 2800.000
39247b214dea7098e8e671e860ecb3f0  -

real	6m46.918s
user	6m44.545s
sys	0m0.132s

qulinxao ★★☆
()
Ответ на: комментарий от qnikst

и какие же нативные для питона числа и как они умножаются в рантайме питона? Просвети меня, великий Ктулху.

насчет тормозов в нех - попробуй принтом выведи без приведения к нех. И как же она реализована? Расскажи ка, откудова тм тормоза?

AIv ★★★★★
() автор топика
Ответ на: комментарий от qulinxao

ну, это к вопросу о пральных алгоритмах:-) Я поленился такое делать, через map и reduce она неочевидно реализуется

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

чисто на функе ( том же хаскеле ) вполне на map reduce и ленивые списки факториал отлично раскладыается

ибо

нужны простые / подсчёт степени простого в факториале / свёртка степеней в ответ.

т.е на хаскеле можно однострочник на ваять

да и на питоне можно - знать бы его .

qulinxao ★★☆
()
Ответ на: комментарий от Harald

без меня, у меня нету 32х;-)

за код спасибо. Буквы маленькие, но м.б. там конец строки еще приехал...

AIv ★★★★★
() автор топика
Ответ на: для 1000000 моё от qulinxao

для 1000000 твоё ( ни чё так комнату подогрел :) )

18:11:28 ~/t 25
$less /proc/cpuinfo|grep 'model' |tail -n 1;less /proc/cpuinfo|grep 'cpu MHz'|tail -n 1; time python -c 'print hex(reduce(long.__mul__,range(1,1000000+1),1L))[2:-1]'|md5sum
model name	: AMD Athlon(tm) II X2 220 Processor
cpu MHz		: 2800.000
39247b214dea7098e8e671e860ecb3f0  -

real	19m12.855s
user	16m29.578s
sys	2m37.134s
18:32:21 ~/t 26
$
qulinxao ★★☆
()
Ответ на: комментарий от AIv

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

насчет тормозов в нех - попробуй принтом выведи без приведения к нех. И как же она реализована? Расскажи ка, откудова тм тормоза?

можно тоже самое, но по русски? Я очень-то верю, что мои рассказы будут иметь смысл, но если нескольким людям будет интересно откуда тормоза при выводе через Numeric.showHex или Text.Lazy.Builder.Int.hexadecimal без использования -O.

а сравнивать haskell и python без hex не интересно, 0.05 против 0.45 в пользу haskell.

qnikst ★★★★★
()
less /proc/cpuinfo | grep 'model' | tail -n 1; less /proc/cpuinfo | grep 'cpu MHz' | tail -n 1; time scala -e "println(List.range(1, 10000+1).foldLeft(BigInt(1))((a,b)=>a*b).toString(16))" | md5sum
model name	: Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz
cpu MHz		: 800.000
3de6339590fbdf0a1c0ae2f2b820f8bf  -

real	0m1.075s
user	0m0.964s
sys	0m0.052s

тормозной scala repl тут.

RedPossum ★★★★★
()
Ответ на: комментарий от qnikst

никуда посылать не надо, щеки пролсто сдуй;-)

попробуй померять сколько стоит в питоне приведение к строке 10000! и вызов hex для него же. И откуда берутся тормоза, которые основные по твоему, при вызове hex, если она по идее тупо конвертит данные байт в два?

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

никуда посылать не надо, щеки пролсто сдуй;-)

поверь, надо.

попробуй померять сколько стоит в питоне приведение к строке 10000! и вызов hex для него же. И откуда берутся тормоза, которые основные по твоему, при вызове hex, если она по идее тупо конвертит данные байт в два?

ммм я про haskell.. в целом предлагаю тебе ещё раз самому подумать, про ffi вызовы и почему в python версия с hex работает в 2 раза быстрее, чем версия без hex, и как следствие почему это не корретный бенчмарк.

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 1)
Ответ на: комментарий от qnikst

ну и ещё может зависеть от того, как openssl собран, там можно выбирать между ассемблерной и Сишной реализацией некоторых кусков

Harald ★★★★★
()
Ответ на: комментарий от Harald

хм.. у меня openssl без gmp собран, могу с ним попробовать. Ещё стоит «Disable EC/RC5 algorithms (as they seem to be patented)» но оно к делу относиться не должно ведь?

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

поверь, надо.

Надо? Ну хорошо. ВОт тут Функциональная языкометрия (комментарий) Вы заявили «в задаче основные тормоза в hex» что несколько не вяжется с вот этим «в python версия с hex работает в 2 раза быстрее, чем версия без hex»

Как минимум это неумение связно формулировать свои мысли, как максимум просто бред. В купе с неоправданным надуванием щек и хамством, у меня возникает острое желание послать Вас, Саша, в игнор-лист. Почему я не должен этого делать, кроме того что мы коллеги?

AIv ★★★★★
() автор топика

Поскольку, как всем известно, основное предназначение различных функциональных ЯП состоит в расчете факториалов, давайте померяемся - какой ЯП это делает быстрее

Так толсто, что я чуть не лопнул, пока читал. Даже интересно, есть ли сколько-нибудь универсальные библиотеки, которые на практике считают факториал быстрее, чем это делает GMP.

Manhunt ★★★★★
()
Ответ на: комментарий от AIv

Ручками, ручками, через алгебраические операции.

Думаешь, на ЛОР-чане найдется хотя бы две дюжины человек, которые способны сделать это ручками с удовлетворительным быстродействием и которым притом не западло тратить на это своё время?

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

надо тут написать расчёт факториала на ассемблере в несколько потоков, как эталон для сравнения :)

Harald ★★★★★
()
Ответ на: комментарий от anonymous

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

Скорее всего, увидели бы познания отдельно взятых регистрантов и анонимусов в дискретной математике. Хороший алгоритм на басике вдрызг уделает прямолинейную реализацию на asm+sse.

Manhunt ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.