尝试并行化Sage代码会使用@parallel decorator或multiprocessing.P创建“线程挂起失败”和“未处理的SIGABRT”错误

2024-05-10 12:01:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一些Sage代码,我正试图并行化,但遇到了一些问题,即“线程挂起失败”和“未处理的SIGABRT”错误。我曾尝试过使用Python的multiprocessing.Pool类,但后来按照kcrisman的建议修改了使用Sage的@parallel类,但是无论我使用哪个,都会出现相同的错误。在

我似乎无法创建一个最小的工作示例来重现这些错误,因此下面是我的代码片段:

@parallel
def calculate_translation(direction, interval, tr):
    g = Graphics()
    translations = {}


    discontinuities = tr.intervals[interval]
    num_discontinuities = len(discontinuities)


    (left_lbl, left_pt) = tr.interval_to_surface(interval, discontinuities[0])
    left_offset = tr.T.offsets[left_lbl]
    g += circle((left_offset[0] + left_pt[0], left_offset[1] + left_pt[1]),
                0.05, color='purple', fill=true)

    for i in xrange(1, num_discontinuities):
        (right_lbl, right_pt) = tr.interval_to_surface(interval, discontinuities[i])
        right_offset = tr.T.offsets[right_lbl]
        g += circle((right_offset[0] + right_pt[0], right_offset[1] + right_pt[1]),
                    0.05, color='purple', fill=true)

        # Determine the midpoint of the interval, then find
        # the corresponding point on the surface.
        mid_pt = (discontinuities[i-1] + discontinuities[i]) / 2
        (sq_lbl, pt0) = tr.interval_to_surface(interval, mid_pt, top_square = true)
        square = tr.T.surface.squares[sq_lbl]
        (x, y) = pt0

        # Determine where the corresponding square sits in the
        # picture.  Draw a red circle at the midpoint, where
        # our geodesic starts.
        (x0, y0) = tr.T.offsets[sq_lbl]
        g += circle((x0 + x, y0 + y), 0.05, color='red', fill=true)

        while true:
            # We are starting from init_square
            init_square = square.name

            # Get the coordinates (inside init_square) of our starting point.
            (x0, y0) = pt0

            # Get the coordinates (inside init_square) of the terminal point,
            # before entering the next square, and also record the new square.
            (x1, y1, next_square) = square.nextpt(pt0, direction)

            # Determine the offsets of the square (for drawing)
            (x_offset, y_offset) = tr.T.offsets[init_square]


            # Draw the piece of the geodesic inside of init_square
            g += line([(x0 + x_offset, y0 + y_offset),
                       (x1 + x_offset, y1 + y_offset)],
                      color='blue')

            if y1 == 1:
                # If we hit the top of init_square, check to
                # see if we've received one of the intervals.

                if tr.bottom_squares.count(init_square) > 0:
                    # bottom_squares records the squares, in
                    # the lower copies of the table, whose
                    # upper edge lies on an interval.  If
                    # we've started from such a square and hit
                    # its top edge, then we've returned to our
                    # interval.
                    terminal_square = init_square
                    (x_terminal, y_terminal) = (x1, y1)
                    break

                elif tr.top_squares.count(next_square.name) > 0:
                    # If the next square we would move
                    # into lives above the interval, then
                    # stop.  We need to reset the point so
                    # that we can use interval_to_surface
                    # later.
                    terminal_square = next_square.name
                    pt0 = TReturn.reset_point((x1, y1), direction)
                    (x_terminal, y_terminal) = pt0
                    break

            # If we did not yet hit one of our intervals,
            # rinse and repeat.
            pt0 = TReturn.reset_point((x1, y1), direction)
            square = next_square

        # Out of while loop, still in for loop.
        # have terminal_square, and (x_terminal, y_terminal) point
        (image_interval, image_pt) = tr.surface_to_interval(terminal_square,
                                                            (x_terminal, y_terminal))


        # Add image point to the graph.
        (x_offset, y_offset) = tr.T.offsets[terminal_square]
        g += circle((x_offset + x_terminal, y_offset + y_terminal), 0.05,
                    color='orange', fill=true)

        distance_to_left = mid_pt - discontinuities[i-1]
        translation = image_pt - distance_to_left
        translation = translation.full_simplify()

        translations[i] = (image_interval, translation)

    return (g, interval, translations)

class TReturn:
    # Other methods are defined, but not relevant.

    def parallel_calculate_translations(self):        
        graphic = Graphics()


        job_args = [(self.angle, key, self) for key in self.intervals.keys()]
        results = [x[1] for x in calculate_translation(job_args)]

        ## I tried using multiprocessing.Pool as well, but the same errors occurred. 
        # pool = Pool(2)        
        # results = pool.map(calculate_translation_helper, job_args)
        # pool.close()
        # pool.join()


        for i in xrange(0, len(results)):
            (g, interval, translation) = results[i]
            graphic += g
            self.translations[interval] = translation

        return graphic

运行代码时,将打印以下内容:

^{pr2}$

这种情况会在以下情况发生之前发生几次,代码会过早退出:

^{3}$

Tags: ofthetorightptinitlefttranslation