I would like to thank all that helped with questions. My apologies for
the very, very, very long message below. I tried to detail my recent
experiences.
I have spent a fair amount of the last 4 days playing with PicoLisp. I
thought I would give it a try even though it is quite primitive feeling
to a person who is used to the richness of a Smalltalk. But it brings
its own benefits. Small, efficient, the ability to understand the
language and implementation. It seems for now that I am not at a level
to use PicoLisp well. And I don't have the time to reach that point at
the moment. But I don't like just appearing and disappearing without
giving the wonderful people here the benefit of learning from my
experience. Unfortunately it will be based on probably unreproducible
experiences. Hopefully this will help someone.
The app I was exploring does a lot of floating point math. Simple
calculations, but lots of them and repetitively. The fixpoint system of
PicoLisp has been quite painful unfortunately.
I have a micro-benchmark that I wrote to test languages to see how they
compare. And yes, I understand micro-benchmarks do not tell all about a
language. But this does represent reasonably the domain I am exploring.
I have explored with this benchmark C/C++, Java, Kotlin, Lua, LuaJit,
Python, Python with Numpy, Nim, Pharo (Smalltalk), Dart all on my
reasonably fast i7 laptop. They range in performance from about 2.4
minutes to over 6 hours to perform.
I ported this to PicoLisp and have experienced much pain. The port was
not straightforward. And I have yet to get it to work. The benchmark is
written in a way which all language should give the exact same results
at the end of the test.
One of my big problems is that PicoLisp has continually segfaulted on me
for unknown reasons. Something as simple as this has segfaulted.
jimmie@squirrel:~/Dev/languagetest$ pil +
: (version)
17.5.16
-> (17 5 16)
: (scl 12)
-> 12
: (*Scl)
Segmentation fault (core dumped)
I will readily admit that when operating on my ported code that it could
be my fault. I readily admit my code at any of the stages of its
development could be broken and cause segfaults. However, when I broke
it down in to smaller and smaller pieces in order to test out each
piece, I have the above type problem of segfaults.
I will admit that I am out of my element when developing with a file
based language. I do not know how to use debuggers or learn how to
examine a core dump. Pharo delivers a live experience. Segfaults are
rare and considered to be bad and should never happen. When they do it
is attempt to reproduce them to fix either the vm or image. User coding
errors should never cause a crash in Pharo. They is its model and the
common one of Smalltalks. I am not trying to say that PicoLisp should be
the same. Just explaining my experience.
I had trouble getting my code to run. When I did, it did not give the
same results as any of the other implementations. So I began to reformat
so that I could explore to find the problem and fix. I figure it has to
do with the fixpoint verse floating point.
Dealing with fixpoint some conclusions.
Set *Scl as soon as possible.
Set *Scl for the smallest precision that will satisfy your requirements.
*Scl size has significant impact on performance and memory.
As frequently as possible, every calculation that sets a variable if
possible. Have your function restore everything to the desired *Scl
precision. Failure to do so affects performance and memory.
Natural integers and fixpoint do not play well with each other. In my
benchmark I have loops which I use the index of the loop in the
calculations. I had to insure that I did (* index 1.0) every time.
Anytime I encounter a natural integer from some source, this needs to be
done. If not, you will not get the proper results. This is stated in the
documentation. But it does require additional effort to insure that
every outside source of data which might provide an integer will have to
be sanitized to work. This is something that feels unnatural in a
dynamically typed language.
I guess at some point you would become accustomed to insuring that you
do all of the above. But it just opens the door for simple mistakes or
oversights when dealing with integers, fixpoint, floating point.
However the segfault problem is really stopping me from even attempting
to overcome these issues. Below I have my code as it currently stands.
My apologies if it is really ugly. I haven't yet learned Lisp. I have
run the code for 1 rep sometimes successfully. The original test runs
for 100 reps. It has never done so. It segfaults every time at 3 and
above. Memory has been a constant 3.6mb ram. It doesn't grow and run out
of memory. It just dies. :(
Below is with one rep.
jimmie@squirrel:~/Dev/languagetest$ pil picoLisp-9.l +
: (doit)
"*Scl: " 12
"createlist"
"loop1"
25.360 sec
"loop2"
"nsum: " "11242.949400372845"
"navg: " "0.390380187512"
25.126 sec
51.657 sec
"nsum: " "11226.617500709850"
"navg: " "0.389813107663"
-> "0.389813107663"
: (bye)
Attempting the full 100.
jimmie@squirrel:~/Dev/languagetest$ pil picoLisp-9.l +
: (doit)
"*Scl: " 12
"createlist"
"loop1"
Segmentation fault (core dumped)
At the first rate it would take about 1 1/2 hours to complete. If *Scl
12 would give the correct results. But it doesn't complete so I don't
know. Comparing 1 rep doesn't match at the moment. But I am tired of
segfaults and am giving up. I don't have the time for further
exploration for a road I don't think I will pursue. I have experienced
probably 40-50 segfaults over the last 2 days. It is inconsistent.
Sometimes it will run, and sometimes not. It has not been a reproducible
experience.
I am not blaming anybody or anything and fully understand I can be
responsible for all of my problems. I also know that PicoLisp could be
at a place that is beyond my current capabilities. I just wanted to
provide my experience hoping someone might benefit.
Thanks for everything.
A successful 100 rep run should give an
nsum: 11322.307098752284 and
navg: 0.393135663151121 within acceptable floating point differences.
Here is the code. It could be broken, buggy and ugly.
(scl 12)
(de average (l)
(/ (sum + l) (length l)))
(de normalize (n)
(if (= n 0.0)
(setq nn 0.000123456789)
(setq nn n))
(while (<= nn 0.0001)
(setq nn (*/ nn 10.0 1.0)))
(while (>= nn 1.0)
(setq nn (*/ nn 0.1 1.0)))
nn)
(de createlist (lsize)
(setq l (range 1 lsize))
(for I (length l)
(set (nth l I) (normalize (* (nth l I 1) 1.0))))
l)
(de loop1calc (i j n)
(setq v
(*/ n
(+ (* i 1.0) n)
(- (* j 1.0) n)
0.1234567
(* 1.0 1.0 1.0)))
(normalize (*/ v v v (* 1.0 1.0))))
(de loop2calc (i j n)
(normalize
(*/ n
(+ (* j 1.0) 1.0)
(+ n n n)
0.1234567
(* 1.0 1.0 1.0))))
(de loop1 (l reps)
(for I reps
(for J (length l)
(setq n (nth l J 1))
(set (nth l J) (loop1calc I J n))
(setq nsum (sum + l))
(setq navg (average l)))))
(de loop2 (l reps)
(for I reps
(for J (length l)
(setq n (nth l J 1))
(set (nth l J) (loop2calc I J n))
(setq nsum (sum + l))
(setq navg (average l)))))
(de doit ()
(println "*Scl: " *Scl)
(bench
(setq reps 100)
(setq n 1.0)
(setq nsum 0.0)
(setq navg 0.0)
(println "createlist")
(setq l (createlist (* 60 24 5 4)))
(println "loop1")
(bench (loop1 l reps))
(println "loop2")
(println "nsum: " (format nsum *Scl))
(println "navg: " (format navg *Scl))
(bench (loop2 l reps)))
(println "nsum: " (format nsum *Scl))
(println "navg: " (format navg *Scl)))
On 07/13/2017 12:25 AM, Alexander Burger wrote:
Hi Jimmie,
What I didn't see in any of the examples is this
: (format (*/ 9.9 9.789 9.56789 `(* 1.0 1.0)) *Scl)
-> "927.23474457900000000000"
Good idea! I added this example to the reference of '*/'
♪♫ Alex
--
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe