2012-11-11 12 views
6

में से निपटने (मैं मुख्य रूप से और के माध्यम से ही जीएमपी-पुस्तकालय का एक अप्रत्यक्ष प्रयोक्ता हूँ। लेकिन मैं इस समस्या को ठीक करने में बहुत ज्यादा दिलचस्पी है।)ओवरफ्लो जीएमपी पॉव

जब हास्यास्पद मान अधिक exponentiations प्रदर्शन, होस्ट-सिस्टम या जीएमपी अब ओवरफ्लो को उचित तरीके से संभालने में सक्षम नहीं हैं। मैंने उपरोक्त सिस्टम के डेवलपर्स से बात की है, लेकिन उन्हें इसके लिए एक आसान फिक्स नहीं दिख रहा है।

क्या यह समस्या अन्य जीएमपी सिस्टम/उपयोगकर्ताओं को ज्ञात है? आप इस तरह के अतिप्रवाह कैसे संभालते हैं?

के रूप में एक मानसिक स्वास्थ्य की जांच पहले 7^7^7 जो होना चाहिए के लिए मूल्य का परीक्षण: 375,982 ... 32343

32-बिट सिस्टम पर, उदाहरण के लिए क्वेरी ?- X is 13^1150000000. पैदावार इस तरह के एक अतिप्रवाह। यहां बताया गया है YAP देता है:

 
GNU gdb (GDB) 7.0-ubuntu 
Copyright (C) 2009 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
and "show warranty" for details. 
This GDB was configured as "i486-linux-gnu". 
For bug reporting instructions, please see: 
... 
Reading symbols from /opt/gupu/src/yap-6.3/narch-gupu2/yap...done. 
(gdb) run -f 
Starting program: /opt/gupu/src/yap-6.3/narch-gupu2/yap -f 
YAP 6.3.2 (i686-linux): Sun Nov 11 04:19:37 CET 2012 
?- X is 13^1150000000. 

Program received signal SIGSEGV, Segmentation fault. 
0x001638d8 in ??() from /usr/lib/libgmp.so.3 
(gdb) bt 
#0 0x001638d8 in ??() from /usr/lib/libgmp.so.3 
#1 0x00164470 in __gmpn_mul_fft() from /usr/lib/libgmp.so.3 
#2 0x001646c2 in __gmpn_mul_fft_full() from /usr/lib/libgmp.so.3 
#3 0x00165f28 in __gmpn_sqr_n() from /usr/lib/libgmp.so.3 
#4 0x0014b58b in __gmpz_n_pow_ui() from /usr/lib/libgmp.so.3 
#5 0x0014c4a1 in __gmpz_pow_ui() from /usr/lib/libgmp.so.3 
#6 0x080c4a1d in Yap_gmp_exp_int_int (i1=13, i2=1150000000) at ../C/gmp_support.c:939 
#7 0x0815f9df in p_exp (t1=, t2=3082051592) at ../C/arith2.c:609 
#8 0x080b1f19 in Eval (t=0) at ../C/eval.c:147 
#9 0x080b2251 in p_is() at ../C/eval.c:186 
#10 0x0806b56a in Yap_absmi (inp=0) at ../C/absmi.c:6912 
#11 0x080b3655 in exec_absmi (top=) at ../C/exec.c:1002 
#12 0x080b3b1f in do_goal (t=, CodeAdr=, arity=, 
    pt=0x0, top=1) at ../C/exec.c:1068 
#13 0x080b3d1d in Yap_RunTopGoal (t=135918154) at ../C/exec.c:1291 
#14 0x08061a6f in YAP_RunGoalOnce (t=135918154) at ../C/c_interface.c:2511 
#15 0x0805c2f5 in do_top_goal (argc=2, argv=0xbffff4c4) at ../console/yap.c:84 
#16 exec_top_level (argc=2, argv=0xbffff4c4) at ../console/yap.c:131 
#17 main (argc=2, argv=0xbffff4c4) at ../console/yap.c:172 
(gdb) 

संपादित करें: यह भी 64-बिट सिस्टम के लिए सच है; इसलिए जैसे:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.3.5) 
Copyright (c) 1990-2012 University of Amsterdam, VU Amsterdam 
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software, 
and you are welcome to redistribute it under certain conditions. 
Please visit http://www.swi-prolog.org for details. 

For help, use ?- help(Topic). or ?- apropos(Word). 

?- X is 3445^2^62. 
gmp: overflow in mpz type 
Abort 
हालांकि

,

?- X is 2^2^63. 
ERROR: Out of global stack 
?- X is 2^2^62. 
gmp: overflow in mpz type 
Abort 

और नीचे से:

?- X is 2^2^36. 
ERROR: Out of global stack 
?- X is 2^2^37. 
gmp: overflow in mpz type 
Abort 

तो, अगर संख्या काफी बड़ी है, त्रुटि SWI से पता चला है - और इस तरह हो सकता है एसडब्ल्यूआई द्वारा नियंत्रित (त्रुटि: संदेश एसडब्ल्यूआई द्वारा है)।

उत्तर

1

ठीक है, ऐसा लगता है मैं किस्मत से बाहर हूँ:

Even the most recent version

 
    fprintf (stderr, "gmp: overflow in mpz type\n"); 
    abort(); 

कम से कम इस अतिप्रवाह नियंत्रित किया जाता है करता है और एक का फायदा उठाने के रूप में इस्तेमाल नहीं किया जा सकता।

और जीएमपी का उपयोग करने वाली कोई भी प्रणाली जिसमें इस समस्या नहीं है, या तो संशोधित लाइब्रेरी का उपयोग करना चाहिए या आकार का आकलन करने के लिए कार्यक्षमता को डुप्लिकेट करना चाहिए।

2

13^1,150,000,000 लगभग 2^4,255,505,675 है जो प्रतिनिधित्व करने के लिए 4,255,505,675 बिट्स लेते हैं। प्रति बिट 8 बिट्स के साथ, यह लगभग 500 एमबी मेमोरी है। लगता है कि यह फिट होना चाहिए।

शायद गणना में शामिल कुछ अस्थायी चर शामिल हैं और यह प्रक्रिया आकार सीमा से अधिक है।

+1

हाल के संस्करणों में यह संदेश और बंदरगाहों को प्रिंट करता है। इस तरह से ओवरफ्लो को एप्लिकेशन द्वारा नियंत्रित नहीं किया जा सकता है। इस मामले में एसडब्ल्यूआई-प्रोलॉग – false

+0

क्या आपने एसडब्ल्यूआई-प्रोलॉग के 64-बिट संस्करण की कोशिश की है? –

+1

यूप - ऊपर देखें, 6.3.5 सिर्फ एक घंटे से भी कम समय के लिए बाहर है ... – false

1

ऐसा लगता है कि आपके पास एक क्रे बिछा हुआ है, तो यह काम करेगा।

#if defined (_CRAY) && ! defined (_CRAYMPP) 
/* plain `int' is much faster (48 bits) */ 
#define __GMP_MP_SIZE_T_INT  1 
typedef int   mp_size_t; 
typedef int   mp_exp_t; 
#else 
#define __GMP_MP_SIZE_T_INT  0 
typedef long int  mp_size_t; 
typedef long int  mp_exp_t; 
#endif 
+1

यह सुनिश्चित करने के लिए: मुझे जो दिलचस्पी है वह एक साफ त्रुटि प्राप्त करने के लिए है जिसे सीधे एसडब्ल्यूआई द्वारा संभाला जा सकता है। – false

+0

यूनिक्स abort() सिग्नल SIGABRT उत्पन्न करता है। यदि आपके पास एसआईजीएबीआरटी के लिए हैंडलर है, तो प्रक्रिया मर जाएगी नहीं। –

+0

दुर्भाग्य से, बहुत मोटे: ओवरफ्लो आमतौर पर उपयोगकर्ता द्वारा प्रदत्त मॉलोक द्वारा संभाला जाता है। इस तरह के मामलों को छोड़कर। – false

3

कुछ है कि कुछ लोगों करना इस समस्या के समाधान के लिए (असमर्थित और यह कुछ स्मृति लीक है, लेकिन वे यह कुछ नहीं से बेहतर लगता है): जीएमपी आप एक प्रतिस्थापन संभाजक (mp_set_memory_functions) निर्दिष्ट करने देता। इस आवंटक से, आप मॉलोक को कॉल कर सकते हैं और यदि यह विफल हो जाता है तो आप एक सी ++ अपवाद फेंक सकते हैं (यदि आप जीसीसी का उपयोग करते हैं, तो कृपया gmp के साथ जीएमपी को दोबारा सम्मिलित करें) या जीएमपी की विफलता हैंडलिंग को बाईपास करने के समान कुछ कॉल करें और आपके द्वारा नियंत्रित कोड पर वापस जाएं।

+1

धन्यवाद! कुछ समय के लिए इसे पचाने की जरूरत है :-)! – false

+1

http://stackoverflow.com/questions/3558684/avoiding-abort-in-libgmp –

4

वास्तव में कोई जवाब नहीं है, लेकिन एक स्पष्टीकरण जो एसडब्ल्यूआई-प्रोलॉग करता है।सबसे पहले, यह अनुमान लगाता है कि एक अतिप्रवाह हो सकता है। यदि यह सुनिश्चित है, तो जीएमपी को कॉल करने से पहले यह एक त्रुटि उठाएगा। अन्यथा, यह जीएमपी आवंटन हुक पर निर्भर करता है और विफलता पर एक longjmp() करता है। यह ट्रैक करता है कि आवंटन निरस्त जीएमपी ऑपरेशन के लिए आवंटित स्मृति को क्या और हटा देता है। यह ऐसा कर सकता है क्योंकि स्मृति जीएमपी के नियंत्रण में स्थायी रूप से स्थायी नहीं है। सफल जीएमपी गणना के परिणाम प्रोलॉग स्टैक पर कॉपी किए गए हैं और प्रोलॉग मेमोरी प्रबंधन के अधीन हैं।

यह काम करता था, लेकिन यह हाल के संस्करणों में काम नहीं करता है। मुझे संदेह है कि जीएमपी आकार का अनुमान लगाता है और मॉलोक() हुक को कॉल करने से भी परेशान नहीं होता है अगर यह जानता है कि यह असफल हो रहा है। मुझे बस यह सुनिश्चित करने का एक तरीका है कि हुक को हमेशा हास्यास्पद रूप से बड़े मूल्य के साथ भी बुलाया जाता है। जो कुछ आकार_टी का प्रतिनिधित्व कर सकता है उससे बड़ा है, हुक को (size_t) -1 के साथ कॉल कर सकता है।

पी। प्रोलॉग रनटाइम स्टैक की प्रतिलिपि बनाने के कारण यह कितनी मेमोरी स्टोर कर सकता है उससे पहले बहती है।

+1

इस पर कोई अपडेट? – false

संबंधित मुद्दे