
it seems that haskell versions of bignums is pretty much gone from more recent discussions of gmp replacements. now, I assume that there are lots of optimizations that keep gmp popular that one wouldn't want to have to reproduce, so that a haskell variant might not be competitive even if one had an efficient representation, but - do all those who want to distribute binaries, but not dynamically linked, need bignums? - it would be nice to know just how far off a good haskell version would be performance-wise.. - what would be a killer for numerical programming, might still be quite acceptable for a substantial part of haskell uses? of course, the real gmp replacement project might be going so well that a haskell version would be obsolete rather sooner than later, and i certainly don't want to interfere with that effort. all that being said, it occurred to me that the representations and fusions described in the nice "rewriting haskell strings" paper would be a good foundation for a haskell bignum project, wouldn't they? http://www.cse.unsw.edu.au/~dons/fps.html http://hackage.haskell.org/trac/ghc/wiki/ReplacingGMPNotes has anyone been looking into this option? just another thought, claus ps. while I'm at it: claiming that "array fusion .. has received comparatively little attention" sounds a bit dangerous to me, and the references are all too limited - even if you meant "in the Haskell world" (and PADL is no Haskell event). you might want to try searching with some other search terms, keeping in mind that most of the work will have been done for not so declarative languages: it isn't my area, but "loop fusion" and "with-loop folding" come to mind, and I'm sure that all those array language and numerical programming folks would be rather, well, disappointed?, to see their efforts ignored like that.

claus.reinke:
it seems that haskell versions of bignums is pretty much gone from more recent discussions of gmp replacements. now, I assume that there are lots of optimizations that keep gmp popular that one wouldn't want to have to reproduce, so that a haskell variant might not be competitive even if one had an efficient representation, but
- do all those who want to distribute binaries, but not dynamically linked, need bignums? - it would be nice to know just how far off a good haskell version would be performance-wise.. - what would be a killer for numerical programming, might still be quite acceptable for a substantial part of haskell uses?
of course, the real gmp replacement project might be going so well that a haskell version would be obsolete rather sooner than later, and i certainly don't want to interfere with that effort.
all that being said, it occurred to me that the representations and fusions described in the nice "rewriting haskell strings" paper would be a good foundation for a haskell bignum project, wouldn't they?
http://www.cse.unsw.edu.au/~dons/fps.html http://hackage.haskell.org/trac/ghc/wiki/ReplacingGMPNotes
has anyone been looking into this option?
Interesting, what kind of operations can you imagine fusing?
just another thought, claus
ps. while I'm at it: claiming that "array fusion .. has received comparatively little attention" sounds a bit dangerous to me, and the references are all too limited - even if you meant "in the Haskell world" (and PADL is no Haskell event\emph{).,
Yes, clearly this is in reference to rewriting-based/combinator-based deforestation. Space constraints meant we couldn't address imperative loop fusion strategies in any depth. Cheers, Don

Hi
- do all those who want to distribute binaries, but not dynamically linked, need bignums? - it would be nice to know just how far off a good haskell version would be performance-wise.. - what would be a killer for numerical programming, might still be quite acceptable for a substantial part of haskell uses?
One advantage you probably haven't thought of is the size of the binary. Currently GMP adds about 50Kb on to the Yhc runtime, for what in the most cases is probably an occasional addition. If the bytecode for a bignum library was less than this then there could be a substantial size saving. (Of course, Yhc has absolutely no license issues with libgmp, and would have substantially worse performance than GHC at bignum optimisation) Thanks Neil

At Sat, 18 Nov 2006 00:44:32 +0000, Neil Mitchell wrote
One advantage you probably haven't thought of is the size of the binary. Currently GMP adds about 50Kb on to the Yhc runtime, for what in the most cases is probably an occasional addition. If the bytecode for a bignum library was less than this then there could be a substantial size saving.
On a related note -- dropping the gmp requirement would also make it easier to port yhc to non-unix platforms. I have tried on a few occasions to compile the yhc runtime for PalmOS, but I can never get gmp built for PalmOS. So, a byte-code version could be advantageous there too. I don't plan to do a lot of bignum intensive computation, so it would not be a problem if the byte-code version was 10 or 100 times slower. j.

Hi Jeremy, On Nov 17, 2006, at 10:34 PM, Jeremy Shaw wrote:
At Sat, 18 Nov 2006 00:44:32 +0000, Neil Mitchell wrote
One advantage you probably haven't thought of is the size of the binary. ...
On a related note -- dropping the gmp requirement would also make it easier to port yhc to non-unix platforms.
I have tried on a few occasions to compile the yhc runtime for PalmOS, but I can never get gmp built for PalmOS.
What is the problem building GMP for PalmOS? According to the GMP install documentation, it supports ARM and Motorola's m68k processors, so you would not be using generic C code. You are probably also using PRC-Tools, correct? Cheers, Pete

At Sun, 19 Nov 2006 13:46:10 -0500, Peter Tanski wrote:
What is the problem building GMP for PalmOS? According to the GMP install documentation, it supports ARM and Motorola's m68k processors, so you would not be using generic C code. You are probably also using PRC-Tools, correct?
Yes. I can not get past the configure step. I tried to build gmp 4.2.1 with prc tools 2.3. I ran configure with these options: ./configure --build=i386-linux-gnu --host=m68k-palmos But, all the test programs (conftest.c) fail to link because they use 'main ()', but palmos expects 'PilotMain ()'. I hack the configure script and changed all occurances of 'main ()' to 'PilotMain ()', but then it failed beacuse the test programs could not find MemoryMgr.h. So I invoked configure with: CFLAGS=-I=/root/n-heptane/projects/haskell/palmos/sdk-5r3/include/ ./configure --build=i386-linux-gnu --host=m68k-palmos But now it fails to find working compiler with this error (from config.log): configure:7756: checking build system compiler m68k-palmos-gcc -I=/root/n-heptane/projects/haskell/palmos/sdk-5r3/include/ configure:7769: m68k-palmos-gcc -I=/root/n-heptane/projects/haskell/palmos/sdk-5r3/include/ conftest.c /usr/lib/gcc-lib/m68k-palmos/2.95.3-kgpd/libgcc.a(_exit.o)(.text+0x10): In function `exit': libgcc2.c: undefined reference to `_cleanup' /usr/lib/gcc-lib/m68k-palmos/2.95.3-kgpd/libgcc.a(_exit.o)(.text+0x16):libgcc2.c: undefined reference to `_exit' collect2: ld returned 1 exit status And, around this time, my interest in running yhi on PalmOS starts to wane. j. "Using autoconf is like playing chess from 20 feet away by flicking a rope to move the pieces" -mbp

On Nov 19, 2006, at 3:20 PM, Jeremy Shaw wrote:
At Sun, 19 Nov 2006 13:46:10 -0500, Peter Tanski wrote:
What is the problem building GMP for PalmOS? According to the GMP install documentation, it supports ARM and Motorola's m68k processors, so you would not be using generic C code. You are probably also using PRC-Tools, correct?
Yes. I can not get past the configure step. I tried to build gmp 4.2.1 with prc tools 2.3. I ran configure with these options:
./configure --build=i386-linux-gnu --host=m68k-palmos
But, all the test programs (conftest.c) fail to link because they use 'main ()', but palmos expects 'PilotMain ()'. I hack the configure script and changed all occurances of 'main ()' to 'PilotMain ()', but then it failed beacuse the test programs could not find MemoryMgr.h. So I invoked configure with:
CFLAGS=-I=/root/n-heptane/projects/haskell/palmos/sdk-5r3/ include/ ./configure --build=i386-linux-gnu --host=m68k-palmos
But now it fails to find working compiler with this error (from config.log):
configure:7756: checking build system compiler m68k-palmos-gcc -I=/ root/n-heptane/projects/haskell/palmos/sdk-5r3/include/ configure:7769: m68k-palmos-gcc -I=/root/n-heptane/projects/haskell/ palmos/sdk-5r3/include/ conftest.c /usr/lib/gcc-lib/m68k-palmos/2.95.3-kgpd/libgcc.a(_exit.o)(.text +0x10): In function `exit': libgcc2.c: undefined reference to `_cleanup' /usr/lib/gcc-lib/m68k-palmos/2.95.3-kgpd/libgcc.a(_exit.o)(.text +0x16):libgcc2.c: undefined reference to `_exit' collect2: ld returned 1 exit status
Did you set LDFLAGS to point to the prc-tools directory and set the first available 'ld' executable to the prc-tools 'ld'? I would help more but I am using darwinports to build prc-tools (I have not experience with prc-tools or PalmOS) and it fails to build (partly because Apple gcc 4.0.1 defaults to a dynamic C++ library, so prebinding fails... there is an easy workaround so once I get enough CPU-time to rebuild it I will try poking around some more.
And, around this time, my interest in running yhi on PalmOS starts to wane.
Awww... to my knowledge, that would be the first Haskell implementation for PalmOS :) As I mentioned in a prior email, there is a Haskell arbitrary precision number library (BigFloat, at http:// bignum.sourceforge.net/). You might adapt it for Integer and add it to Yhc if nothing else works. I'm not crazy about BigFloat's performance, though. Cheers, Pete

p.tanski:
On Nov 19, 2006, at 3:20 PM, Jeremy Shaw wrote:
And, around this time, my interest in running yhi on PalmOS starts to wane.
Awww... to my knowledge, that would be the first Haskell implementation for PalmOS :) As I mentioned in a prior email, there is a Haskell arbitrary precision number library (BigFloat, at http:// bignum.sourceforge.net/). You might adapt it for Integer and add it to Yhc if nothing else works. I'm not crazy about BigFloat's performance, though.
Pretty sure Tony Sloane et al at Macquarie have had nhc98 running on the palm for quite a while. They've recently moved to YHC though, iirc. -- Don

On Nov 22, 2006, at 8:39 PM, Donald Bruce Stewart wrote:
p.tanski:
to my knowledge, that would be the first Haskell implementation for PalmOS...
Pretty sure Tony Sloane et al at Macquarie have had nhc98 running on the palm for quite a while. They've recently moved to YHC though, iirc.
Donald, Thanks for tip! Have you seen any of this code yourself? Jeremy, Dr. Sloane would be a good person to contact. For reference, the last work on this seems to have been done in 2005. Tony Sloane (asloane -at- ics dot mq dot edu dot au). Patroklos Argyroundis did a port of GMP version 3.1.1 to WinCE, noted at http://ntrg.cs.tcd.ie/~argp/software/ntrg-gmp-wince.html . I don't know if that might give any good pointers. Cheers, Pete

Hi Neil, On Nov 17, 2006, at 7:44 PM, Neil Mitchell wrote:
- do all those who want to distribute binaries, but not dynamically linked, need bignums? - it would be nice to know just how far off a good haskell version would be performance-wise.. - what would be a killer for numerical programming, might still be quite acceptable for a substantial part of haskell uses?
One advantage you probably haven't thought of is the size of the binary. Currently GMP adds about 50Kb on to the Yhc runtime, for what in the most cases is probably an occasional addition. If the bytecode for a bignum library was less than this then there could be a substantial size saving.
The entire static GMP library is 1.090976 MB on my machine (Mac OS X), so 50KB is not much for the static linker to include. A replacement library should be smaller (written in Haskell it would be much larger but only included as necessary): maybe 30-40KB. Depending on the compiler used for the replacement library, the code could be even smaller (for Intel it might be larger, for Microsoft CL, IBM XL or Sun CC it should be smaller). GCC has historically produced relatively large binaries; though v4.2 might be a little better I can't count on that as MinGW still distributes 3.5. The replacement library would still add a bit to every binary if it was included in the runtime. Fortunately for Yhc, bytecode programs may be much smaller. For other Haskell compilers dynamic libraries are only alternative to a library (as opposed to primitive) implementation of Integer.
(Of course, Yhc has absolutely no license issues with libgmp, and would have substantially worse performance than GHC at bignum optimisation)
That is always subject to change :) Cheers, Pete

On Nov 17, 2006, at 7:24 PM, Claus Reinke wrote:
it seems that haskell versions of bignums is pretty much gone from more recent discussions of gmp replacements. now, I assume that there are lots of optimizations that keep gmp popular that one wouldn't want to have to reproduce, so that a haskell variant might not be competitive even if one had an efficient representation, but
- do all those who want to distribute binaries, but not dynamically linked, need bignums?
You are right: most don't. Even when working with larger numbers, I have very rarely used bignum libraries myself, mostly because there is usually a clever--and often faster--way to deal with large numbers, especially when you don't require all that extra precision. These methods were better known and relatively widely used before multi-precision libraries became so widespread and have even become more useful since 64-bit machines and C99's 64-bit ints came around. Integers are mostly a convenience. Large numbers are necessary if you need very high precision mathematical calculations or if you are doing cryptography; for that matter, high precision mathematics usually benefits more from arbitrary precision decimal (fixed or floating point) for certain calculations. The simple problem with Haskell and Integer is that, according to the Standard, Integer is a primitive: it is consequently implemented as part of the runtime system (RTS), not the Prelude or any library (though the interface to Integer is in the base library). For GHC, compiling with -fno-implicit-prelude and explicitly importing only those functions and types you need the won't get rid of Integer. Possible solutions would be to implement the Integer 'primitive' as a separate library and import it into the Prelude or base libraries, then perform an optimisation step where base functions are only linked in when needed. Except for the optimisation step, this actually makes the job easier since Integer functions would be called using the FFI and held in ForeignPtrs. (I have already done the FFI- thing for other libraries and a primitive version of the replacement.)
- it would be nice to know just how far off a good haskell version would be performance-wise..
There is actually a relatively recent (2005, revised) Haskell version of an old Miranda library for "infinite" precision floating point numbers by Martin Guy, called BigFloat, at http:// bignum.sourceforge.net/. Of course, it is floating point and Integers would be faster but the general speed difference between the two would probably be proportional to the speed difference in C and so would be just as disappointing. The BigFloat library (using the Haskell version) came in last place at the Many Digits "Friendly" Competition for 2005 (see http://www.cs.ru.nl/~milad/manydigits/ final_timings_rankings.html), though you would probably be more interested in looking at the actual timing results to get a better idea. (The fastest competitors were MPFR, which uses GMP, and The Wolfram Team, makers of Mathematica; BigFloat actually beat iRRAM and Maple solutions for several problems.) The real problem with an Integer library written in *pure* Haskell-- especially with Integers--is simple: Haskell is too high-level and no current Haskell compiler, even JHC, has even remotely decent support for low-level optimisations such as being able to unroll a loop over two arrays of uint32_t and immediately carry the result from adding the first elements from each array to the addition of the next two, in two machine instructions. I shouldn't have to mention parallelization of operations. In short, if you look at general assembler produced from any Haskell compiler, it is *very* ugly and Arrays are even uglier. (For a simple comparison to Integer problems, try implementing a fast bucket sort in Haskell.) GMP uses hand-written assembler routines for many supported architectures, partly because GMP was originally created for earlier versions of GCC which could not optimise as well as current versions. Even GMP cannot compare to an optimised library using SIMD (Altivec, SSE)--in my tests, SIMD-optimised algorithms are between 2x to 10x faster. SIMD and small assembler routines (especially for architectures without SIMD, especially) are what I have been doing the bulk of my work on. I doubt I have the ability to extend the current state of the art with regard to higher-level polynomial optimisations, so I am always trying out any algorithm I can find. (For very high precision multiplication (more than 30,000 bits), not much beats a SIMD-enabled Fast Fourier Transform; a specially coded Toom-3 algorithm would be faster but for very large operands the algorithm becomes prohibitively complex. Division is another labour- intensive area.)
- what would be a killer for numerical programming, might still be quite acceptable for a substantial part of haskell uses?
Quite possibly, yes. I haven't done my own study on what most users actually require but from notes in the source code of the Python multi-precision integer library (LongObject), they found most users of their library never needed more than 2 or 3 uint32_t in length. (They had originally reserved 5 uint32_t of space for a newly created PyLongObject.) Of course even ordinary users would notice a change in speed if they used a much slower library on larger numbers (79 decimal digits, 256 bits, or more) in an interactive session.
of course, the real gmp replacement project might be going so well that a haskell version would be obsolete rather sooner than later, and i certainly don't want to interfere with that effort.
Not at all. All ideas gratefully received :) It's going slowly, partly because I am constantly having to learn more, test and refactor so the result isn't a naive solution. I could reimplement GMP, of course, but many of the GMP algorithms are not readily amenable to SIMD operations--I am trying to *beat* GMP in speed.
all that being said, it occurred to me that the representations and fusions described in the nice "rewriting haskell strings" paper would be a good foundation for a haskell bignum project, wouldn't they?
They would. Thanks for the link--I had been working from the source code. A Haskell-C combined solution may sometimes be faster--I noticed this before now while experimenting with using a random number generator library written in C, and came to the conclusion that the speed was largely due to Haskell's ability to cache the results of many operations, sometimes better than I could predict on my own. Term rewriting for a hybrid Haskell-C library could be very useful for complex polynomials. It might use equational transformations or Template Haskell, GHC's own Ian Lynagh did some work on this http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh/ Fraskell/ (on Fraskell, with some code examples); and see esp., http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh/papers/ Template_Haskell-A_Report_From_The_Field.ps (PostScript file)). The one problem I have with using equational transformations over arrays is that it seems very difficult--I would say, impossible without modifying the compiler--to perform a transformation that works between two combined arrays when the the array-operands may be of different sizes. This is similar to the solution FFTW (see http://www.fftw.org) uses, only they used OCaml to perform the analysis on particular equations and patch the higher-level combinations together again in C--FFTW is essentially an equational compiler. The problem with many of FFTW's optimisations are that much of their analysis relies on constant values--you are writing a program to solve one defined mathematical problem where you know something from the beginning, such as the size of the operands (that's a biggie!). The SPIRAL project uses similar methods for more basic operations, such as multiplierless constant multiplication (transform multiplication of an unknown value with a constant into an optimal number of left-shifts and additions). See, e.g., http://www.spiral.net/hardware/multless.html. When writing an arbitrary precision Integer library for Haskell it must be more general than that: I have to assume no constants may be available. It is essentially an optimisation problem--but this whole endeavour is, in a way. Cheers, Pete

On Sat, Nov 18, 2006 at 04:46:24PM -0500, Peter Tanski wrote:
The simple problem with Haskell and Integer is that, according to the Standard, Integer is a primitive: it is consequently implemented as part of the runtime system (RTS), not the Prelude or any library (though the interface to Integer is in the base library). For GHC, compiling with -fno-implicit-prelude and explicitly importing only those functions and types you need the won't get rid of Integer. Possible solutions would be to implement the Integer 'primitive' as a separate library and import it into the Prelude or base libraries, then perform an optimisation step where base functions are only linked in when needed. Except for the optimisation step, this actually makes the job easier since Integer functions would be called using the FFI and held in ForeignPtrs. (I have already done the FFI- thing for other libraries and a primitive version of the replacement.)
there is no requirement that Integer be a primitive. a plain old implementation in haskell or via the FFI is certainly a valid one. John -- John Meacham - ⑆repetae.net⑆john⑈

Hello John, Tuesday, November 28, 2006, 4:52:09 AM, you wrote:
The simple problem with Haskell and Integer is that, according to the Standard, Integer is a primitive: it is consequently implemented as part of the runtime system (RTS),
there is no requirement that Integer be a primitive. a plain old implementation in haskell or via the FFI is certainly a valid one.
as a part of my Core library i've defined simplest implementation of Integer for poor compilers: newtype Integer = Integer Int plusInteger = liftI2 plusInt ... it's also possible to use [Int] here if some poor compilers will really arrive -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com
participants (7)
-
Bulat Ziganshin
-
Claus Reinke
-
dons@cse.unsw.edu.au
-
Jeremy Shaw
-
John Meacham
-
Neil Mitchell
-
Peter Tanski