1

I was performing a little experiment to see if I could extract some numbers that reflected the power of the CPU the machine was using when I came across a very strange issue that had something to do with pickling, though this seems to have been raised by tkinter, as I hadn't heard of "pickling" until I hit this. Here's the error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Ben\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1549, in __call__
    return self.func(*args)
  File "C:\Users\Ben\Desktop\test.py", line 79, in multicore
    p1.start()
  File "C:\Users\Ben\AppData\Local\Programs\Python\Python35-32\lib\multiprocessing\process.py", line 105, in start
    self._popen = self._Popen(self)
  File "C:\Users\Ben\AppData\Local\Programs\Python\Python35-32\lib\multiprocessing\context.py", line 212, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Users\Ben\AppData\Local\Programs\Python\Python35-32\lib\multiprocessing\context.py", line 313, in _Popen
    return Popen(process_obj)
  File "C:\Users\Ben\AppData\Local\Programs\Python\Python35-32\lib\multiprocessing\popen_spawn_win32.py", line 66, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Users\Ben\AppData\Local\Programs\Python\Python35-32\lib\multiprocessing\reduction.py", line 59, in dump
    ForkingPickler(file, protocol).dump(obj)
AttributeError: Can't pickle local object 'multicore.<locals>.one'

and here's the relevant bit of code: First, the line that calls the function:

button2 = ttk.Button(frame, text = "Run Benchmark 2", command = multicore).grid(row = 2, column = 2)

And second, the function:

def multicore():
    var1 = 1
    var2 = 1
    var3 = 1
    var4 = 1
    var5 = 1
    var6 = 1
    spent1 = 0
    spent2 = 0
    spent3 = 0
    spent4 = 0
    spent5 = 0
    spent6 = 0

    start = time.time()
    cores = multiprocessing.cpu_count()

    def one():
        while var1 <= 1000000000:
            var1 = var1 * 1.0000001
        spent1 = time.time() - start

    def two():
        while var2 <= 1000000000:
            var2 = var2 * 1.0000001
        spent2 = time.time() - start

    def three():
        while var3 <= 1000000000:
            var3 = var3 * 1.0000001
        spent3 = time.time() - start

    def four():
        while var4 <= 1000000000:
            var4 = var4 * 1.0000001
        spent4 = time.time() - start

    def five():
        while var5 <= 1000000000:
            var5 = var5 * 1.0000001
        spent5 = time.time() - start

    def six():
        while var6 <= 1000000000:
            var6 = var6 * 1.0000001
        spent6 = time.time() - start

    if __name__=='__main__':
        p1 = Process(target = one)
        p2 = Process(target = two)
        p3 = Process(target = three)
        p4 = Process(target = four)
        p5 = Process(target = five)
        p6 = Process(target = six)

        if cores == 1:
            p1.start()
        elif cores == 2:
            p1.start()
            p2.start()
        elif cores == 3:
            p1.start()
            p2.start()
            p3.start()
        elif cores == 4:
            p1.start()
            p2.start()
            p3.start()
            p4.start()
        elif cores == 5:
            p1.start()
            p2.start()
            p3.start()
            p4.start()
            p5.start()
        elif cores == 6:
            p1.start()
            p2.start()
            p3.start()
            p4.start()
            p5.start()
            p6.start()

    totalspent = spent1 + spent2 + spent3 + spent4 + spent5 + spent6

    multiresult.set(round(8000 - (totalspent * 100)))

What's supposed to happen is the function will take the number of CPU cores and start that many loops of multiplication to see how quickly they get done, and then turn that into a score comparable to the scores of other machines. Also, please excuse my excessive 'tard status as I'm not the greatest programmer.

edit: problem solved by moving def(): statements out of multicore()

Blckknght
  • 100,903
  • 11
  • 120
  • 169
Ben Lonc
  • 11
  • 4
  • Related questions seem to be here: http://stackoverflow.com/questions/8804830/python-multiprocessing-pickling-error?rq=1 and http://stackoverflow.com/questions/11685073/pickling-error-when-multithreading-design-or-code-issue?rq=1 – eric Apr 07 '16 at 03:35
  • Is that indentation correct or are `def one():` and etc..., indented one level so that they are part of the `multicore` function? Are you running on Windows? Is this python 2 or 3? – tdelaney Apr 07 '16 at 04:18
  • Could you strip out most of those functions and `p2.start` etc... and still get the error. It would be nice to have a small example. – tdelaney Apr 07 '16 at 04:19
  • `multiprocessing` needs to serialize data to send it to child processes. It uses the native [python pickle protocol](https://docs.python.org/3/library/pickle.html) to do that. In Windows, `multiprocessing` needs to "pickle" a significant number of objects to make things go. If your indentation is not correct and those functions are actually indented and part of the `multicore` function the solution would be to move them out of that function. – tdelaney Apr 07 '16 at 04:23

0 Answers0