Multiprocessingでクラス内変数が、どう変化するかの確認

##概要
Python3でクラスを定義して、メソッド中にクラス変数を書き換える手続きを記載しつつ、それをマルチプロセスで処理したらクラス変数がどうなるのかの確認。

##クラスの割当→並列処理→計算
###プログラム
####test_main.py

```py3
#!/usr/bin/env python
# vim:fileencoding=utf-8
#Author: Hamano TASUKE
#Created: 2016-01-05

import sys
from test_class import TestMultiProcess
argvs = sys.argv
argc = len(argvs)

def calculate_helper(class_name, method_name, *args, **kwargs):
    return getattr(class_name, method_name)(*args, **kwargs)

def main():

    alpha = 2
    beta = 3
    test = TestMultiProcess(alpha, beta)
    array = [[1,2,3], [2,3,4], [4,5,6,7],[1,2,3]]
    result = test.parallel_calculation(4, array)

    print("Multiprocess result")
    print(result)
    print("Class-inner variable alpha after calculation:%i" % test.get_alpha())
    print("Class-inner variable beta after calculation:%i" % test.get_beta())

if __name__ =='__main__':
    main()

```

####test_class.py

```py3
#!/usr/bin/env python
# vim:fileencoding=utf-8
#Author: Hamano TASUKE
#Created: 2016-01-05

import numpy as np
import multiprocessing as mp
import itertools as itrt
from time import sleep

class TestMultiProcess:
    def __init__(self, alpha, beta):
        self.alpha = alpha
        self.beta = beta

    def calculate(self, a):
        sleep(5)
        print(a)
        a_np = np.array(a)
        a_np = a_np * 2
        self.alpha += len(a)
        self.beta += len(a)**2
        return a_np

    def parallel_calculation(self, core_num, array):
        pool = mp.Pool(core_num)
        args = itrt.izip(itrt.repeat(self), itrt.repeat('calculate'), array)
        result = pool.map(tomap, args)
        return result

    def get_alpha(self):
        return self.alpha

    def get_beta(self):
        return self.beta

def toapply(class_name, method_name, *args, **kwargs):
    return getattr(class_name, method_name)(*args, **kwargs)

def tomap(args):
    return getattr(args[0], args[1])(*args[2:]) 
```

###結果
```
[2, 3, 4]
[4, 5, 6, 7]
[1, 2, 3]
[1, 2, 3]
Multiprocess result
[array([2, 4, 6]), array([4, 6, 8]), array([ 8, 10, 12, 14]), array([2, 4, 6])]
Class-inner variable alpha after calculation:2
Class-inner variable beta after calculation:3
```

メソッド内では変更したクラス変数が使用されますが、プロセスの外側ではクラス変数が変化しないままのようです。
pool.mapやpool.applyはクラスのメソッドインスタンスを受け付けないので、[multiprocessing.Poolがエラーになる人へ](http://aflc.hatenablog.com/entry/20110825/1314366131)から拝借したヘルパー関数を使用しています。

##並列処理→クラスの割当→計算
###プログラム
####test_main.py
```py3

#!/usr/bin/env python
# vim:fileencoding=utf-8
#Author: Hamano TASUKE
#Created: 2016-01-17

import sys
import multiprocessing as mp
from test_class import TestMultiProcess
def arg_wrapper(args):
    return args[0](*args[1:])

def assign_and_calculation(alpha, beta, array):
    test = TestMultiProcess(alpha, beta)
    calculate_result = test.calculate(array)
    return (test.get_alpha(), test.get_beta(), calculate_result)

def main():
    alpha = 2
    beta = 3
    array = [[1,2,3], [2,3,4], [4,5,6,7],[1,2,3]]
    argument = [(assign_and_calculation, alpha, beta, each) for each in array]

    pool = mp.Pool(4)
    result = pool.map(arg_wrapper, argument)

    print("Multiprocess result")
    print([each[2] for each in result])
    print("Class-inner variable alpha after calculation:%s" % str([each[0] for each in result]))
    print("Class-inner variable beta after calculation:%s" % str([each[1] for each in result]))

if __name__ =='__main__':
    main() 
```
####test_class.py
```py3
#!/usr/bin/env python
# vim:fileencoding=utf-8
#Author: Hamano TASUKE
#Created: 2016-01-17

import numpy as np
import itertools as itrt
from time import sleep

class TestMultiProcess:
    def __init__(self, alpha, beta):
        self.alpha = alpha
        self.beta = beta

    def calculate(self, a):
        sleep(5)
        print(a)
        a_np = np.array(a)
        a_np = a_np * 2
        self.alpha += len(a)
        self.beta += len(a)**2
        return a_np

    def get_alpha(self):
        return self.alpha

    def get_beta(self):
        return self.beta 
```
###結果
```
[4, 5, 6, 7]
[1, 2, 3]
[1, 2, 3]
[2, 3, 4]
Multiprocess result
[array([2, 4, 6]), array([4, 6, 8]), array([ 8, 10, 12, 14]), array([2, 4, 6])]
Class-inner variable alpha after calculation:[5, 5, 6, 5]
Class-inner variable beta after calculation:[12, 12, 19, 12]
```
インスタンス宣言に使う変数をヘルパー関数でラッピングすることで複数の引数を渡す事が可能です([Python で並列計算 (multiprocessing モジュール) | 複数の引数を取る関数を map() メソッドで並列に走らせる](http://d.hatena.ne.jp/kochory/20111015/1318632397)より)。これを利用して並列処理中でインスタンスを宣言することで、クラス内変数の計算も可能です(あまり使いみちないかも…)。

##参考
* [Python multiprocessing.Pool: when to use apply, apply_async or map?](http://stackoverflow.com/questions/8533318/python-multiprocessing-pool-when-to-use-apply-apply-async-or-map)
* [multiprocessing.Poolがエラーになる人へ](http://aflc.hatenablog.com/entry/20110825/1314366131)
* [Python で並列計算 (multiprocessing モジュール) | 複数の引数を取る関数を map() メソッドで並列に走らせる](http://d.hatena.ne.jp/kochory/20111015/1318632397)