The Computer Language
23.03 Benchmarks Game

mandelbrot Python 3 #2 program

source code

# The Computer Language Benchmarks Game
# https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
#
# contributed by Tupteq
# modified by Simon Descarpentries
# modified for multi-core by Ahmad Syukri

import multiprocessing as mp
import sys

def writer(buff_queue,size):  #i/o is slow, so leave it to only one worker
    from array import array
    buff_pos = 0
    buff = []
    cout = sys.stdout.buffer.write
    while 1:
        try:
            buff.append(buff_queue.get_nowait())
        except:
            if len(buff):
                buff.sort() 
                pos = len(buff) - 1 
                while pos>0:
                    if buff[pos][0] == buff[pos-1][1]:  #connect contiguous segment
                        buff[pos-1] = (buff[pos-1][0],buff[pos][1],buff[pos-1][2]+buff[pos][2])
                        del(buff[pos])
                    pos-=1
                if buff[0][0]==buff_pos:  # write if segment is the next needed one
                    cout(array('B', buff[0][2]).tostring())
                    buff_pos = buff[0][1]
                    del(buff[0])

            if buff_pos>=size:
                break

def worker(size, task_queue, buff_queue):
    cout = sys.stdout.buffer.write
    fsize = float(size)
    r_size = range(size)
    r_iter = range(50)
    local_abs = abs
    result = []
    y=size  #only to ensure task_head is initialized. not so pretty code
    while 1:
        task = task_queue.get()
        if task is None:
            if len(result):  # push remaining segments
                buff_queue.put((task_head,y+1,result))
            break
        elif task-y-1:
            if len(result):      # try to resume from previous segment unless broken
                buff_queue.put((task_head,y+1,result))
            task_head = task
            result = []
        #got new job
        y = task
        bit_num = 7
        byte_acc = 0
        fy = 2j * y / fsize - 1j
        for x in r_size:
            z = 0j
            c = 2. * x / fsize - 1.5 + fy
     
            for i in r_iter:
                z = z * z + c
                if local_abs(z) >= 2.: break
            else:
                byte_acc += 1 << bit_num
     
            if bit_num == 0:
                result.append(byte_acc)
                bit_num = 7
                byte_acc = 0
            else:
                bit_num -= 1
        if bit_num != 7:
            result.append(byte_acc)

def main():
    size = int(sys.argv[1])
    task_queue = mp.Queue()
    for i in range(size):
        task_queue.put(i)
    buff_queue = mp.Queue()
    num_proc = 64 
    proc = []
    for i in range(num_proc):
        task_queue.put(None)

    worker_args = (size, task_queue, buff_queue)

    for a in range(num_proc):
        p = mp.Process(target=worker, args=worker_args)
        p.start()
        proc.append(p)
    sys.stdout.write("P4\n%d %d\n" % (size, size))
    w = mp.Process(target=writer, args=(buff_queue,size))
    w.start()
    proc.append(w)

    for p in proc:
        p.join()

if __name__=='__main__':
    main()

    

notes, command-line, and program output

NOTES:
64-bit Ubuntu quad core
Python 3.11.1


Tue, 24 Jan 2023 19:31:43 GMT

MAKE:
mv mandelbrot.python3-2.python3 mandelbrot.python3-2.py
pyright .
No configuration file found.
No pyproject.toml file found.
stubPath /home/dunham/all-benchmarksgame/benchmarksgame_i53330/mandelbrot/tmp/typings is not a valid directory.
Assuming Python platform Linux
Searching for source files
Found 1 source file
pyright 1.1.288
/home/dunham/all-benchmarksgame/benchmarksgame_i53330/mandelbrot/tmp/mandelbrot.python3-2.py
  /home/dunham/all-benchmarksgame/benchmarksgame_i53330/mandelbrot/tmp/mandelbrot.python3-2.py:29:49 - error: Cannot access member "tostring" for type "array[int]"
    Member "tostring" is unknown (reportGeneralTypeIssues)
  /home/dunham/all-benchmarksgame/benchmarksgame_i53330/mandelbrot/tmp/mandelbrot.python3-2.py:48:33 - error: "task_head" is possibly unbound (reportUnboundVariable)
  /home/dunham/all-benchmarksgame/benchmarksgame_i53330/mandelbrot/tmp/mandelbrot.python3-2.py:52:33 - error: "task_head" is possibly unbound (reportUnboundVariable)
3 errors, 0 warnings, 0 informations 
Completed in 2sec
make: [/home/dunham/all-benchmarksgame/2000-benchmarksgame/nanobench/makefiles/u64q.programs.Makefile:388: mandelbrot.python3-2.python3_run] Error 1 (ignored)

3.66s to complete and log all make actions

COMMAND LINE:
/opt/src/Python-3.11.1/bin/python3 -OO mandelbrot.python3-2.py 1000

TIMED OUT after 800s


(BINARY) PROGRAM OUTPUT NOT SHOWN

Process Process-65:
Traceback (most recent call last):
  File "/home/dunham/all-benchmarksgame/benchmarksgame_i53330/mandelbrot/tmp/mandelbrot.python3-2.py", line 18, in writer
    buff.append(buff_queue.get_nowait())
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/src/Python-3.11.1/lib/python3.11/multiprocessing/queues.py", line 135, in get_nowait
    return self.get(False)
           ^^^^^^^^^^^^^^^
  File "/opt/src/Python-3.11.1/lib/python3.11/multiprocessing/queues.py", line 116, in get
    raise Empty
_queue.Empty

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/src/Python-3.11.1/lib/python3.11/multiprocessing/process.py", line 314, in _bootstrap
    self.run()
  File "/opt/src/Python-3.11.1/lib/python3.11/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/home/dunham/all-benchmarksgame/benchmarksgame_i53330/mandelbrot/tmp/mandelbrot.python3-2.py", line 29, in writer
    cout(array('B', buff[0][2]).tostring())
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'array.array' object has no attribute 'tostring'