Ticket #10018: 10018_pari_sig_retry.patch

File 10018_pari_sig_retry.patch, 14.9 KB (added by jdemeyer, 11 years ago)

New patch, ignore previous

  • sage/libs/pari/gen.pyx

    # HG changeset patch
    # User Jeroen Demeyer <jdemeyer@cage.ugent.be>
    # Date 1287342612 -7200
    # Node ID 686dd317527cb89817e5b74637d6de5fb85ba1c6
    # Parent  a5d003d9e9bf1c2e042faa7e10aea0c61207664b
    #10018: Implement _pari_trap() using sig_retry()
    
    diff -r a5d003d9e9bf -r 686dd317527c sage/libs/pari/gen.pyx
    a b  
    174174
    175175# The unique running Pari instance.
    176176cdef PariInstance pari_instance, P
    177 pari_instance = PariInstance(16000000, 500000)
     177pari_instance = PariInstance()
    178178P = pari_instance   # shorthand notation
    179179
    180180# so Galois groups are represented in a sane way
     
    85848584
    85858585
    85868586cdef class PariInstance(sage.structure.parent_base.ParentWithBase):
    8587     def __init__(self, long size=16000000, unsigned long maxprime=500000):
     8587    def __init__(self, long size=10000000, unsigned long maxprime=500000):
    85888588        """
    85898589        Initialize the PARI system.
    85908590       
     
    86578657        self.PARI_TWO = self.new_gen_noclear(gen_2)
    86588658        sig_off()
    86598659
     8660    def debugstack(self):
     8661        r"""
     8662        Print the internal PARI variables ``top`` (top of stack), ``avma``
     8663        (available memory address, think of this as the stack pointer),
     8664        ``bot`` (bottom of stack).
     8665       
     8666        EXAMPLE::
     8667           
     8668            sage: pari.debugstack()  # not tested
     8669            top =  0x60b2c60
     8670            avma = 0x5875c38
     8671            bot =  0x57295e0
     8672            size = 10000000
     8673        """
     8674        # We deliberately use low-level functions to minimize the
     8675        # chances that something goes wrong here (for example, if we
     8676        # are out of memory).
     8677        global avma, top, bot
     8678        printf("top =  %p\navma = %p\nbot =  %p\nsize = %lu\n", top, avma, bot, <unsigned long>(top) - <unsigned long>(bot))
     8679        fflush(stdout)
     8680
    86608681    def _unsafe_deallocate_pari_stack(self):
    86618682        if bot:
    86628683            sage_free(<void*>bot)
    8663         global top, bot
    8664         top = 0
    8665         bot = 0
     8684        global top, bot, avma
     8685        bot = 0; avma = 0; top = 0
    86668686        pari_close()
    86678687
    86688688    def __repr__(self):
     
    92129232    # Initialization
    92139233    ############################################################
    92149234
     9235    def stacksize(self):
     9236        r"""
     9237        Returns the current size of the PARI stack, which is `10^7`
     9238        by default.  However, the stack size is automatically doubled
     9239        when needed.  It can also be set directly using
     9240        ``pari.allocatemem()``.
     9241       
     9242        EXAMPLES::
     9243           
     9244            sage: pari.stacksize()
     9245            10000000
     9246           
     9247        """
     9248        global top, bot
     9249        return int(<unsigned long>(top) - <unsigned long>(bot))
     9250
     9251    def _allocate_huge_mem(self):
     9252        r"""
     9253        This function allocates an impossibly large amount of PARI
     9254        stack in order to test ``init_stack()`` failing.
     9255       
     9256        TESTS::
     9257           
     9258            sage: pari.allocatemem(10^6, silent=True)
     9259            sage: pari._allocate_huge_mem()
     9260            Traceback (most recent call last):
     9261            ...
     9262            MemoryError: Unable to allocate ... (instead, allocated 1000000 bytes)
     9263       
     9264        Test that the PARI stack is sane after this failure::
     9265           
     9266            sage: a = pari('2^10000000')
     9267            sage: pari.allocatemem(10^6, silent=True)
     9268        """
     9269        # Since size_t is unsigned, this should wrap over to a very
     9270        # large positive number.
     9271        init_stack(<size_t>(-4096))
     9272
     9273    def _setup_failed_retry(self):
     9274        r"""
     9275        This function pretends that the PARI stack is larger than it
     9276        actually is such that allocatemem(0) will allocate much more
     9277        than double the current stack.  That allocation will then fail.
     9278        This function is meant to be used only in this doctest.  This
     9279        test is successful as long as we do not get any segmentation
     9280        faults.
     9281       
     9282        TESTS::
     9283           
     9284            sage: pari.allocatemem(4096, silent=True)
     9285            sage: pari._setup_failed_retry()
     9286            sage: try:  # Any result is fine as long as it's not a segfault
     9287            ...     a = pari('2^1000000')
     9288            ... except MemoryError:
     9289            ...     pass
     9290            sage: pari.allocatemem(10^6, silent=True)
     9291        """
     9292        global top
     9293        # Pretend top is at a very high address
     9294        top = <pari_sp>(<size_t>(-16))
     9295
    92159296    def allocatemem(self, s=0, silent=False):
    92169297        r"""
    9217         Double the *PARI* stack.
    9218         """
    9219         if s == 0 and not silent:
    9220             print "Doubling the PARI stack."
     9298        Change the PARI stack space to the given size (or double the
     9299        current size if ``s`` is `0`).
     9300       
     9301        The PARI stack is never automatically shrunk.  You can use the
     9302        command ``pari.allocatemem(10^7)`` to reset the size to `10^7`,
     9303        which is the default size at startup.  Note that the results of
     9304        computations using Sage's PARI interface are copied to the
     9305        Python heap, so they take up no space in the PARI stack.
     9306        The PARI stack is cleared after every computation.
     9307       
     9308        It does no real harm to set this to a small value as the PARI
     9309        stack will be automatically doubled when we run out of memory.
     9310        However, it could make some calculations slower (since they have
     9311        to be redone from the start after doubling the stack until the
     9312        stack is big enough).
     9313       
     9314        INPUT:
     9315       
     9316       
     9317        -  ``s`` - an integer (default: 0).  An argument of zero will be
     9318           interpreted as "double the current size".  Otherwise ``s``
     9319           should be the size in bytes of the new PARI stack.
     9320       
     9321       
     9322        EXAMPLES::
     9323       
     9324            sage: pari.allocatemem(10^7)
     9325            PARI stack size set to 10000000 bytes.
     9326            sage: pari.allocatemem()  # Double the current size
     9327            PARI stack size set to 20000000 bytes.
     9328            sage: pari.stacksize()
     9329            20000000
     9330            sage: pari.allocatemem(10^6)
     9331            PARI stack size set to 1000000 bytes.
     9332       
     9333        The following computation will automatically increase the PARI
     9334        stack size::
     9335           
     9336            sage: a = pari('2^100000000')
     9337       
     9338        ``a`` is now a Python variable on the Python heap and does not
     9339        take up any space on the PARI stack.  The PARI stack is still
     9340        large because of the computation of ``a``::
     9341           
     9342            sage: pari.stacksize()
     9343            32000000
     9344            sage: pari.allocatemem(10^7)
     9345            PARI stack size set to 10000000 bytes.
     9346            sage: pari.stacksize()
     9347            10000000
     9348       
     9349        TESTS:
     9350       
     9351        Do the same without using the string interface and starting
     9352        from a very small and odd stack size::
     9353           
     9354            sage: pari.allocatemem(1025)
     9355            PARI stack size set to 1040 bytes.
     9356            sage: a = pari(2)^100000000
     9357            sage: pari.stacksize()
     9358            34078720
     9359        """
    92219360        s = int(s)
    9222         cdef size_t a = s
    9223         if int(a) != s:
    9224             raise ValueError, "s must be nonnegative and not too big."
     9361        if s < 0:
     9362            raise ValueError, "s must be nonnegative."
    92259363        init_stack(s)
     9364        if not silent:
     9365            print "PARI stack size set to", self.stacksize(), "bytes."
    92269366
    92279367    def pari_version(self):
    92289368        return str(PARIVERSION)
     
    96249764
    96259765##############################################
    96269766
    9627 def init_pari_stack(size=8000000):
     9767cdef int init_stack(size_t new_size) except -1:
     9768    r"""
     9769    Low-level Cython function to allocate the PARI stack.  This
     9770    function should not be called directly, use ``pari.allocatemem()``
     9771    instead.
    96289772    """
    9629     Change the PARI scratch stack space to the given size.
    9630    
    9631     The main application of this command is that you've done some
    9632     individual PARI computation that used a lot of stack space. As a
    9633     result the PARI stack may have doubled several times and is now
    9634     quite large. That object you computed is copied off to the heap,
    9635     but the PARI stack is never automatically shrunk back down. If you
    9636     call this function you can shrink it back down.
    9637    
    9638     If you set this too small then it will automatically be increased
    9639     if it is exceeded, which could make some calculations initially
    9640     slower (since they have to be redone until the stack is big
    9641     enough).
    9642    
    9643     INPUT:
    9644    
    9645    
    9646     -  ``size`` - an integer (default: 8000000)
    9647    
    9648    
    9649     EXAMPLES::
    9650    
    9651         sage: get_memory_usage()                       # random output
    9652         '122M+'
    9653         sage: a = pari('2^100000000')
    9654         sage: get_memory_usage()                       # random output
    9655         '157M+'
    9656         sage: del a
    9657         sage: get_memory_usage()                       # random output
    9658         '145M+'
    9659    
    9660     Hey, I want my memory back!
    9661    
    9662     ::
    9663    
    9664         sage: sage.libs.pari.gen.init_pari_stack()
    9665         sage: get_memory_usage()                       # random output
    9666         '114M+'
    9667    
    9668     Ahh, that's better.
    9669     """
    9670     init_stack(size)
    9671 
    9672 cdef int init_stack(size_t size) except -1:
     9773    global top, bot, avma, mytop
     9774    #printf("Stack before init_stack():\ntop =  %p\navma = %p\nbot =  %p\nsize = %lu\n", avma, top, bot, <unsigned long>(top) - <unsigned long>(bot)); fflush(stdout);
     9775
     9776    cdef size_t old_size = <size_t>(top) - <size_t>(bot)
     9777
     9778    # s is the number of bytes which will actually be allocated
    96739779    cdef size_t s
    9674     cdef pari_sp cur_stack_size
    9675 
    9676     global top, bot, avma, mytop
    9677 
    9678 
    9679     err = False    # whether or not a memory allocation error occurred.
    9680 
    9681    
    9682     # delete this if get core dumps and change the 2* to a 1* below.
     9780    if (new_size == 0):
     9781        if old_size >= (<size_t>(1) << (8*sizeof(void*)-1)):
     9782            # We cannot possibly double since we already use over half
     9783            # the addressable memory
     9784            raise MemoryError, "Unable to allocate %s bytes for the PARI stack (instead, allocated %s bytes)"%(2*long(old_size), old_size)
     9785        s = 2 * old_size
     9786    else:
     9787        s = new_size
     9788
     9789    # Align size to 16 bytes and take 1024 bytes as a minimum
     9790    s = ((s + 15)/16)*16
     9791    if (s < 1024):
     9792        s = 1024
     9793   
     9794    # Free the current stack
    96839795    if bot:
    96849796        sage_free(<void*>bot)
    9685 
    9686     prev_stack_size = top - bot
    9687     if size == 0:
    9688         size = 2 * prev_stack_size
    9689 
    9690     # Decide on size
    9691     s = fix_size(size)
     9797        bot = 0; top = 0; avma = 0; mytop = 0
    96929798
    96939799    # Allocate memory for new stack using Python's memory allocator.
    96949800    # As explained in the python/C API reference, using this instead
    96959801    # of malloc is much better (and more platform independent, etc.)
    96969802    bot = <pari_sp> sage_malloc(s)
    96979803
    9698     while not bot:
    9699         err = True
    9700         s = fix_size(prev_stack_size)
     9804    # If doubling failed, instead add 25% to the current stack size.
     9805    if (bot == 0) and (new_size == 0):
     9806        s = old_size + (old_size/64)*16
    97019807        bot = <pari_sp> sage_malloc(s)
    9702         if not bot:
    9703             prev_stack_size /= 2
     9808   
     9809    # If this is non-zero, the size we failed to allocate
     9810    cdef size_t failed_size = 0
     9811    if not bot:
     9812        failed_size = s
     9813        # We lost our PARI stack and are not able to allocate the
     9814        # requested size.  If we just raise an exception now, we end up
     9815        # *without* a PARI stack which is not good.  We will raise an
     9816        # exception later, after allocating *some* PARI stack.
     9817        s = old_size
     9818        while True:
     9819            bot = <pari_sp> sage_malloc(s)
     9820            if bot: break
     9821            s = (s/32)*16
     9822            assert(s >= 1024)  # We are in BIG trouble if this fails!
    97049823   
    97059824    top = bot + s
    97069825    mytop = top
    97079826    avma = top
    9708 
    9709     if err:
    9710         raise MemoryError, "Unable to allocate %s bytes memory for PARI."%size
    9711 
    9712 
    9713 cdef size_t fix_size(size_t a):
    9714     cdef size_t b
    9715     b = a - (a & (sizeof(long)-1))     # sizeof(long) | b <= a 
    9716     if b < 1024:
    9717         b = 1024
    9718     return b
     9827    #printf("Stack after init_stack():\ntop =  %p\navma = %p\nbot =  %p\nsize = %lu\n", avma, top, bot, <unsigned long>(top) - <unsigned long>(bot)); fflush(stdout);
     9828   
     9829    if failed_size:
     9830        raise MemoryError, "Unable to allocate %s bytes for the PARI stack (instead, allocated %s bytes)"%(failed_size, s)
     9831   
     9832    return 0
    97199833
    97209834cdef GEN deepcopy_to_python_heap(GEN x, pari_sp* address):
    97219835    cdef size_t s
     
    97439857    avma = tmp_avma
    97449858    return h
    97459859
    9746 # The first one makes a separate copy on the heap, so the stack
    9747 # won't overflow -- but this costs more time...
     9860# Make a separate copy on the heap, so the stack won't overflow
    97489861cdef gen _new_gen (GEN x):
    97499862    cdef GEN h
    97509863    cdef pari_sp address
     
    98279940
    98289941
    98299942# We expose a trap function to C.
    9830 # If this function returns without raising an exception,
    9831 # the code is retried.
    9832 # This is a proof-of-concept example.
    98339943# THE TRY CODE IS NOT REENTRANT -- NO CALLS TO PARI FROM HERE !!!
    98349944#              - Gonzalo Tornario
    9835 
    9836 cdef void _pari_trap "_pari_trap" (long errno, long retries) except *:
     9945cdef void _pari_trap "_pari_trap" (long errnum) except *:
    98379946    """
    9838     TESTS::
    9839    
     9947    This function is called by _pari_catch in pari_err.h when a PARI
     9948    error occured.  If this function returns without raising an
     9949    exception, the code is retried starting from the sig_on().
    98409950    """
    9841     if retries > 100:
    9842         sig_off()
    9843         raise RuntimeError, "_pari_trap recursion too deep"
    9844     if errno == errpile:
    9845         P.allocatemem(silent=True)
    9846     elif errno == user:
    9847         sig_off()
     9951    sig_off()
     9952    if errnum == errpile:
     9953        # PARI is out of memory.  We double the size of the PARI stack
     9954        # and retry the computation.
     9955        init_stack(0)
     9956    elif errnum == user:
    98489957        raise Exception, "PARI user exception"
    98499958    else:
    9850         sig_off()
    9851         raise PariError, errno
    9852 
     9959        raise PariError, errnum
    98539960
    98549961
    98559962def vecsmall_to_intlist(gen v):
  • sage/libs/pari/pari_err.h

    diff -r a5d003d9e9bf -r 686dd317527c sage/libs/pari/pari_err.h
    a b  
    1414
    1515#define _pari_endcatch { err_leave(__catcherr); }
    1616
    17 /* Careful with pari_retries !
    18  * It should not be in a register, we flag it as "volatile".
    19  */
    2017#define _pari_catch { \
    2118        long pari_errno; \
    22         long volatile pari_retries = 0; \
    2319        jmp_buf __env; \
    2420        __catcherr = 0; \
    2521        if ((pari_errno=setjmp(__env))) { \
    26             _pari_trap(pari_errno, pari_retries); \
    27             if(PyErr_Occurred()) { \
    28                 _pari_endcatch; \
    29                 return NULL; \
    30             } \
    31             pari_retries++; \
     22            _pari_trap(pari_errno); /* Implicitly calls _pari_endcatch */ \
     23            if(PyErr_Occurred()) return NULL; \
     24            sig_retry() \
    3225        } \
    3326        __catcherr = err_catch(CATCH_ALL, &__env); \
    3427    }