LINUX.ORG.RU

Scheme - скорость выполнения кода

 , ,


2

2

Не буду писать многабукаф - просто скажите, сколько (по времени в секундах) в Scheme выполняется данный кот:

(define (divs n)
    (define (go i a)
        (cond ((> (* i i) n) a)
              ((= (* i i) n) (+ 1 a))
              ((= 0 (modulo n i)) (go (+ 1 i) (+ 2 a)))
              (else (go (+ 1 i) a))))
    (go 1 0))
 
(define (task n k)
    (cond ((>= 500 (divs k)) (task (+ 1 n) (+ k n 1))) (else k)))
 
(display (task 1 1))
Я пробовал несколько онлайн вычисляторов, и время выполнения различается на порядки. Где-то указывают реализацию (chiken / guile), где-то нет. Здесь https://repl.it/languages/scheme какое-то неприличное время выполняется, здесь https://www.tutorialspoint.com/execute_scheme_online.php весьма неплохо (относительно остальных), на Ideone и Rextester промежуточные показатели... Я в растерянности - где правда?



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

Мерить время выполения на онлайн-выполняторах глупое занятие. Там настройки выкручены чтоб бы не грузить сервер. Guile как аналог python/ruby-ей никогда скоростью не славился. Chicken-компилятор работает быстро поверх C, что врдяли возможно в онлайн на сервере. А интерпретатор произвольного кода у него не сильно быстрый по идее.

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

По ссылке, где выполняется бесконечно долго, прочитал

BiwaScheme Interpreter version 0.6.4
Copyright (C) 2007-2014 Yutaka HARA and the BiwaScheme team
так что там действительно кто во что горазд... Можете посоветовать оптимальный вариант скачать/установить локально? В принципе в варианте по второй ссылке стартового поста мне более-менее нравится скорость.

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

Можете посоветовать оптимальный вариант скачать/установить локально?

Если ты никогда такого не ставил, то виртуалку с попсовым линуксом и поставить тот же chicken из реп. Хотя все вручную тоже должно работать. Хотя это все таки схемщиков надо спрашивать, я все таки лиспер :)

antares0 ★★★★
()
Последнее исправление: antares0 (всего исправлений: 1)
Welcome to Racket v6.6.
> (time (define (divs n)
    (define (go i a)
        (cond ((> (* i i) n) a)
              ((= (* i i) n) (+ 1 a))
              ((= 0 (modulo n i)) (go (+ 1 i) (+ 2 a)))
              (else (go (+ 1 i) a))))
    (go 1 0))

(define (task n k)
    (cond ((>= 500 (divs k)) (task (+ 1 n) (+ k n 1))) (else k)))

(display (task 1 1)))

76576500cpu time: 1108 real time: 1109 gc time: 0
kovrik ★★★★★
()
$ cat /proc/cpuinfo | grep -m 1 "model name"     
model name	: Intel(R) Xeon(R) CPU E5-1620 v3 @ 3.50GHz

Racket 6.6:

$ time racket -f ./scheme-speed.scm
76576500
racket -f ./scheme-speed.scm  1.06s user 0.05s system 99% cpu 1.111 total

Chez Scheme 9.4:

$ time scheme --script ./scheme-speed.scm 
76576500
scheme --script ./scheme-speed.scm  1.24s user 0.01s system 99% cpu 1.248 total

Guile 2.0.13:

$ time guile ./scheme-speed.scm
76576500
guile ./scheme-speed.scm  4.63s user 0.01s system 99% cpu 4.638 total

Chicken 4.11.0:

$ csc scheme-speed.scm 
$ time ./scheme-speed
76576500
./scheme-speed  4.74s user 0.01s system 99% cpu 4.748 total

Chibi 0.7.3:

$ time chibi-scheme ./scheme-speed.scm
76576500
chibi-scheme ./scheme-speed.scm  9.47s user 0.00s system 99% cpu 9.472 total

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

Guile как аналог python/ruby-ей никогда скоростью не славился. Chicken-компилятор работает быстро поверх C

С тех пор, как в Guile добавили jit, вышесказанное не актуально.

Puzan ★★★★★
()

Такое сравнение не имеет смысла. И абсолютное значение времени выполнения тоже не имеет смысла. Реализуй один и тот же алгоритм на двух языках и тогда ты можешь определить относительную производительность двух реализаций этих языков на подобных задачах.

Gentooshnik ★★★★★
()
 ~/tmp > cat test.rkt 
#lang racket

(define (divs n)
    (define (go i a)
        (cond ((> (* i i) n) a)
              ((= (* i i) n) (+ 1 a))
              ((= 0 (modulo n i)) (go (+ 1 i) (+ 2 a)))
              (else (go (+ 1 i) a))))
    (go 1 0))
 
(define (task n k)
    (cond ((>= 500 (divs k)) (task (+ 1 n) (+ k n 1))) (else k)))
 
(display (task 1 1))
 ~/tmp > raco exe test.rkt 
 ~/tmp > time ./test 
76576500./test  1,25s user 0,03s system 99% cpu 1,287 total
loz ★★★★★
()
Ответ на: комментарий от Ivana

Ivana, мой пост в этой теме имеет смысл, потому что говорит, что вопрос заданный в теме не имеет смысла и предлагает на выбор несколько вопросов, ответы на которые сообщат Вам более осмысленную информацию.

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

Уточню. В вопросе «сколько работает этот код» нет смысла, потому что на это влияет слишком много незафиксированных переменных. Смысл есть в вопросах: 1. Насколько дольше выполняется этот код в одних реализациях Scheme, чем в других при одинаковом железе. На этот вопрос уже ответил Puzan в, объективно, самом осмысленном комментарии в этом треде. 2. Насколько дольше выполняется этот код в реализациях Scheme в сравнении с аналогичным кодом на других языках на одинаковом железе.

Например.

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

Gentooshnik, продолжаете наполнять тему бессмысленными постами? Для контраста?

2 all - поставил Racket 6.6, полет нормальный, спасибо всем, писавшим осмысленно :)

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

Ivana, нет, продолжаю наполнять тему осмысленными постами, а вы продолжаете утверждать, что мои осмысленные посты бессмысленны.

UPD: На самом деле, да. Мой пост действительно был бессмысленным, потому что к тому моменту как я его сделал Puzan уже дал ответ на более осмысленный вопрос, чем тот бессмысленный, который Вы задали в ОП. :)

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

2 all - поставил Racket 6.6, полет нормальный

Однако, Racket это не в полной мере схема. Если хочешь стандарта, то лучше взять Chez.

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

Кстати, вот еще одна реализация:

$ time larceny -- ./scheme-speed.scm
Larceny v0.98 "General Ripper" (Mar  7 2015 01:06:26, precise:Linux:unified)
76576500
larceny -- ./scheme-speed.scm  3.60s user 0.01s system 99% cpu 3.612 total
Puzan ★★★★★
()
Ответ на: комментарий от Puzan

Дело в том, что мне не нужна аутентичная стандартная в полной мере схема. Я просто написал три реализации своего схемоподобного по синтаксису и семантике языка, интерпретаторы. Но поскольку особой оптимизации не делал, скорость выполнения оставляет желать - например кот из стартового поста на паре реализаций выполняется 40 секунд и 3 минуты 50 секунд соответственно. Желая получить возможность убыстрить исполнение, я подумал, что чем самостоятельно пытаться курить JIT или статическую оптимизирующую компиляцию, проще будет попробовать транслировать котов на моем диалекте в какой-нибудь готовый промышленный язык с оптимизациями на борту. Попробовал в Java, но ниасилил победить стековерфлоу. Потом меня осенило, что если не брать спецвозможностей моего диалекта, определяемых платформой реализации, то он синтаксически и семантически похож на схему - почему бы не транслировать в какой-нибудь из ее диалектов? Поскольку локально ничего не стояло, полез в инет на онлайн-РЕПЛы проверять эффективность, удивился результатам и создал эту тему. В результате (спасибо осмысленно пишущим участникам) выбрал Racket (я на винде, измучен мышовыми гуями, да и скорость на примере одна из лучших), и сейчас с интересом узнаю, что можно не только учить мой диалект конвертировать кот в синтаксис схемы (обильно досыпая скобок при этом, что имхо не способствует читабельности и понимабельности), но и написать на Racket реализацию своего диалекта, т.к. в нем присутствуют бортовые возможности для этого - это приятный бонус к скорости, удобному гуевому РЕПЛу, хорошей документации и т.п.

Вот, вкратце, что я хотел сказать о моих целях и мотивации.

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

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

#lang racket

(define (noelem x l) (cond ((null? l) #t) ((equal? x (car l)) #f) (else (noelem x (cdr l)))))
(define (take n l) (cond ((null? l) nil) ((> n 0) (cons (car l) (take (- n 1) (cdr l)))) (else nil)))
(define (drop n l) (cond ((null? l) nil) ((> n 0) (drop (- n 1) (cdr l))) (else l)))
(define nil '())

(begin (display "ЗАДАЧА - решение судоку, реализация поиска в глубину:") (display "\n"))
(define field (quote (0 0 9 3 0 1 8 0 0 0 0 0 0 0 0 0 3 0 2 0 0 0 7 0 0 0 9 1 0 0 2 0 9 0 0 4 0 0 4 0 8 0 2 0 0 8 0 0 7 0 6 0 0 1 9 0 0 0 1 0 0 0 5 0 2 0 0 0 0 0 7 0 0 0 5 6 0 2 4 0 0)))
(define (showField f) (define (go f) (cond ((null? f) "") (else (string-append (foldl (lambda (x a) (string-append a (number->string x) " ")) "" (take 9 f)) "\n" (go (drop 9 f)))))) (cond ((null? f) "Нет решений") (else (go f))))
(begin (display "Стартовое поле:") (display "\n")) (display (showField field))

(define (steps field)
  (define (step-vars i) (begin (define r (/ i 9)) (define c (modulo i 9)) (define rs0 (* 3 (/ r 3))) (define cs0 (* 3 (/ c 3)))) (define (squ-row n) (take 3 (drop (+ cs0 (* 9 (+ rs0 n))) field))) (define (sieve-nth l a) (cond ((null? l) a) (else (sieve-nth (drop 9 l) (cons (car l) a))))) (foldl (lambda (l a) (filter (lambda (x) (noelem x l)) a)) (quote (1 2 3 4 5 6 7 8 9)) (list (squ-row 0) (squ-row 1) (sieve-nth (drop c field) (squ-row 2)) (take 9 (drop (* 9 r) field)) nil)))

  (define (rep-by-ind i e l) (cond ((null? l) nil) ((= 0 i) (cons e (cdr l))) (else (cons (car l) (rep-by-ind (- i 1) e (cdr l))))))

  (define (go i min-i min-step-counts min-step-vars f)
    (cond ((null? f) (cond ((= min-step-counts 100) (cons field nil))
                           ((= min-step-counts 0) nil)
                           (else (map (lambda (v) (rep-by-ind min-i v field)) min-step-vars))))
          ((= 0 (car f)) (begin (define i-step-vars (step-vars i))
                                 (define i-step-counts (length i-step-vars))
                          (cond ((< i-step-counts min-step-counts)
                                 (go (+ i 1) i i-step-counts i-step-vars (cdr f)))
                                (else (go (+ i 1) min-i min-step-counts min-step-vars (cdr f))))))
          (else (go (+ i 1) min-i min-step-counts min-step-vars (cdr f)))))

  (go 0 0 100 0 field))

(define (solve-depth field)
  (define (go f) (define vars (steps f)) (cond ((noelem 0 f) f) ((null? vars) nil) (else (foldl (lambda (x a) (cond ((null? a) (go x)) (else a))) nil vars))))
  (go field))

(begin (display "Решение поиском в глубину:") (display "\n"))
(begin (display (showField (solve-depth field))) (display "\n"))
Конечно можно придраться, что одни define и никаких let, что (display «\n») а не (newline) и т.п. Но для экспресс-варианта имхо катит.

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

Я лохЪ, / моего диалекта надо было заменить на quotient, теперь все работает правильно и даже поиск в ширину до кучи

(define (solve-wide field)
  (display "Количество анализируемых вариантов: ")
  (define (go vars)
    (display (string-append (number->string (length vars)) " "))
    (cond ((null? vars) nil)
          ((noelem 0 (car vars)) vars)
          (else (go (concat (map steps vars))))))
  (go (cons field nil)))

(begin (display "Поиск в ширину ....") (display "\n"))
(define solunions (solve-wide field))
(begin (display "\n") (display "Решения поиском в ширину:") (display "\n"))
(display (cond ((null? solunions) (string-append "Нет решений" "\n"))
               (else (foldl (lambda (x a) (string-append a (showField x) "\n")) "" solunions))))

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

Вот, вкратце, что я хотел сказать о моих целях и мотивации.

Согласен, ракета более подходящий для этого инструмент.

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

А ракета очень даже того

Интересно было бы потестить на более комплексных тестах.

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