
On 10 August 2004 16:04, Remi Turk wrote:
- reset GMP's memory allocators before calling it from your code, and set them back to the RTS allocators afterward. Slow, but it should work. It doesn't solve the problem properly though: external libraries which use GMP are still broken. It does indeed seem to work, after a quick test. (new util.c attached)
And it does solve _my_ immediate "problem": I can surround every gmp-operation with a gmp_begin()/gmp_end() and pretend to be happy. (and anyway, I'm just messing around, failure merely means I've got yet another unfinished project ;))
Part of the reason for all this messy FFIing is your post:
http://www.haskell.org/pipermail/glasgow-haskell-users/2004-June/006767. html Hmm yes, I now realise that it's not quite as easy as I implied in that message. The problem is the memory allocation. If a GMP function allocates some memory, we have to swizzle the pointer that comes back (where swizzle(p) { return p-sizeof(StgArrWords) }). Unfortunately you have to do this without giving the GC a chance to run, and there's no way to get this atomicity in plain Haskell+FFI, which is why the primops are still necessary. Perhaps one way to do it would be to define generic Integer primop wrappers - i.e. one wrapper for an mpz function that takes two arguments and returns one, etc. The primop implementations already work like this, except that the wrappers are CPP macros. If the wrapper were lifted to the level of a primop itself, then you could easily use different mpz functions by calling the appropriate primop passing the address of the mpz function. Cheers, Simon

On Wed, Aug 11, 2004 at 02:27:19PM +0100, Simon Marlow wrote:
On 10 August 2004 16:04, Remi Turk wrote:
http://www.haskell.org/pipermail/glasgow-haskell-users/2004-June/006767.html
Hmm yes, I now realise that it's not quite as easy as I implied in that message. The problem is the memory allocation. If a GMP function allocates some memory, we have to swizzle the pointer that comes back (where swizzle(p) { return p-sizeof(StgArrWords) }). Unfortunately you have to do this without giving the GC a chance to run, and there's no way to get this atomicity in plain Haskell+FFI, which is why the primops are still necessary.
Perhaps one way to do it would be to define generic Integer primop wrappers - i.e. one wrapper for an mpz function that takes two arguments and returns one, etc. The primop implementations already work like this, except that the wrappers are CPP macros. If the wrapper were lifted to the level of a primop itself, then you could easily use different mpz functions by calling the appropriate primop passing the address of the mpz function.
Ah, the "shockingly inefficient" family of GMP_TAKEx_RETy macros ;) (I understand the swizzle-talk only partly, so I'll ignore it and hope my words won't turn out to be utter nonsense..) But as long as GMP doesn't mind about being abused the way my most recent util.c does, I can get away with the mp_set_memory_functions-trick, can't I? ("*Be sure to call `mp_set_memory_functions' only when there are no active GMP objects allocated using the previous memory functions! Usually that means calling it before any other GMP function.*", and using undocumented features) And with this trick and a ffi GMP-binding implement a working Mpz datatype. And when (if?) this is done, drop in a "type Mpz = Integer", rip out all Integer-primops, remove the mp_set_memory_functions-trick and start benchmarking? (Conveniently forgetting that "fromInteger :: Integer -> Integer" most certainly has to stay a primop anyway...) Or is the rts using Integers in such a way that any (standard malloc) allocations are forbidden while e.g. "(*) :: Integer -> Integer -> Integer" is running?
Cheers, Simon
Greetings, Remi -- Nobody can be exactly like me. Even I have trouble doing it.
participants (2)
-
Remi Turk
-
Simon Marlow