Frage

Um eine beliebige precision floating point / Drop-in-Ersatz für Double zu schaffen, ich versuche MPFR die FFI verwenden, aber trotz aller Bemühungen nicht das einfachste Stück Code nicht funktionieren. Es kompiliert, es läuft, aber es stürzt spöttisch nach für eine Weile zu arbeiten vorgibt. Eine einfache C-Version des Codes druckt glücklich mit der Nummer „1“ bis (640 Dezimalstellen) insgesamt 10.000 mal. Die Haskell-Version, wenn Sie gefragt werden, das gleiche zu tun, korrumpiert leise (?) Die Daten nach nur 289 Ausdrucken von „1,0000 ... 0000“ und nach 385 Ausdrucken, verursacht es einen Assertionsfehler und Bomben. Ich bin ratlos, wie da es beim Debuggen dieser vorgehen „funktionieren soll“.

Der Code kann unter http://hpaste.org/10923 und unter http://www.updike.org/mpfr-broken.tar.gz

Ich bin mit GHC 6,83 auf FreeBSD 6 und GHC 6.8.2 unter Mac OS X Hinweis müssen Sie MPFR (getestet mit 2.3.2) für Libs und Header-Dateien mit den richtigen Pfade (Wechsel des Makefile) installiert ( zusammen mit denen von GMP) auf diese erfolgreich zu kompilieren.

Fragen

  • Warum wird die C-Version arbeiten, aber die Haskell-Version Flocke aus? Was bin ich dabei, wenn die FFI anbietet? Ich habe versucht, StablePtrs und hatte genau die gleichen Ergebnisse.

  • Kann jemand überprüfen, ob dies ein Mac / BSD Problem ist nur durch Kompilieren und meinen Code ausgeführt wird? (Ist der C-Code „funktioniert“ arbeitet? Hat der Haskell-Code „noworks“ Arbeit?) Kann jemand auf Linux und Windows Versuch / run zu kompilieren und sehen, ob Sie die gleichen Ergebnisse erhalten?

C-Code: (works.c)

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  

#include <gmp.h>  
#include <mpfr.h>
#include "mpfr_ffi.c"  

int main()  
{  
  int i;  
  mpfr_ptr one;  

  mpf_set_default_prec_decimal(640);  

  one = mpf_set_signed_int(1);  
  for (i = 0; i < 10000; i++)
    {  
      printf("%d\n", i);
      mpf_show(one);
    }  
}  

Haskell Code: (Main.hs --- funktioniert nicht)

module Main where  

import Foreign.Ptr            ( Ptr, FunPtr )  
import Foreign.C.Types        ( CInt, CLong, CULong, CDouble )  
import Foreign.StablePtr      ( StablePtr )  

data MPFR = MPFR  

foreign import ccall "mpf_set_default_prec_decimal"  
    c_set_default_prec_decimal          :: CInt -> IO ()  
setPrecisionDecimal                     :: Integer -> IO ()  
setPrecisionDecimal decimal_digits = do  
    c_set_default_prec_decimal (fromInteger decimal_digits)  

foreign import ccall "mpf_show"  
   c_show                               :: Ptr MPFR -> IO ()  

foreign import ccall "mpf_set_signed_int"  
   c_set_signed_int                     :: CLong -> IO (Ptr MPFR)  

showNums k n = do  
   print n  
   c_show k  

main = do  
   setPrecisionDecimal 640  
   one <- c_set_signed_int (fromInteger 1)  
   mapM_ (showNums one) [1..10000]  
War es hilfreich?

Lösung

Ich sehe das Problem auch auf einem

$ uname -a
Linux burnup 2.6.26-gentoo-r1 #1 SMP PREEMPT Tue Sep 9 00:05:54 EDT 2008 i686 Intel(R) Pentium(R) 4 CPU 2.80GHz GenuineIntel GNU/Linux
$ gcc --version
gcc (GCC) 4.2.4 (Gentoo 4.2.4 p1.0)
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.8.3

Ich sehe auch die Ausgabe von 1,0000 ... 000 bis 1,0000 zu ändern ... [Müll].

Lassen Sie uns sehen, folgendes funktioniert:

main = do
    setPrecisionDecimal 640
    mapM_ (const $ c_set_signed_int (fromInteger 1) >>= c_show) [1..10000]

, die das Problem auf Teile one verengt sich irgendwie während der Laufzeit verprügelt zu werden. Mit Blick auf die Ausgabe von ghc -C und ghc -S, ist aber keine Hinweise geben mir.

Hmm, ./noworks +RTS -H1G funktioniert auch, und ./noworks +RTS -k[n]k für Werte von [n] Variation zeigen Ausfälle auf unterschiedliche Weise.

Ich habe keine festen Leitungen bekam, aber es gibt zwei Möglichkeiten, die mir in den Sinn springen:

  • GMP, die die GHC-Laufzeit verwendet, und MPFR einig seltsame Wechselwirkung mit
  • Stapelspeicher für C-Funktionen innerhalb der GHC Laufzeit aufgerufen ist begrenzt, und MPFR nicht gut tun

Dass gesagt wird ... gibt es einen Grund, warum Sie Ihre eigenen Bindungen sind rollen, anstatt verwenden HMPFR ?

Andere Tipps

Juda Jacobsen beantwortet dies auf der Haskell-Café-Mailingliste:

Dies ist ein bekanntes Problem mit GHC wegen der Art und Weise GHC Anwendungen GMP intern (halten ganzen Zahlen).

Offenbar C-Daten in der Halde wird allein gelassen von GHC in grundsätzlich allen Fällen ist außer Code, der die FFI verwendet GMP oder eine C-Bibliothek zuzugreifen, die (wie MPFR auf GMP beruht, die ich wollte verwenden ). Es gibt einige Workarounds (schmerzhaft), aber die „richtige“ Art und Weise sein, würde entweder hacken GHC (hart) oder die Simons bekommen GHC Abhängigkeit von GMP (härter) zu entfernen.

Aleš Bizjak, Betreuer des HMPFR geschrieben Haskell -Cafe und zeigte, wie GHC, um zu verhindern Zuordnung der Gliedmaßen zu steuern (und damit sie allein, statt GCing sie verlassen und clobbering sie):

mpfr_ptr mpf_new_mpfr()  
{  
  mpfr_ptr result = malloc(sizeof(__mpfr_struct));  
  if (result == NULL) return NULL;  
  /// these three lines:  
  mp_limb_t * limb = malloc(mpfr_custom_get_size(mpfr_get_default_prec()));  
  mpfr_custom_init(limb, mpfr_get_default_prec());  
  mpfr_custom_init_set(result, MPFR_NAN_KIND, 0, mpfr_get_default_prec(), limb);  
  return result;  
}

Für mich ist dies viel einfacher als die Anstrengung Beteiligung an einen Ersatz für GMP in GHC zu schreiben, die die einzige Alternative wären, wenn ich wirklich jede Bibliothek, die abhängig von GMP verwenden will.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top