Cython 演習問題

演習1 - 素数判定

(A) 以下のPythonスクリプトを作成し、 primes(1000) の実行に必要な処理時間を測定せよ。
def primes(kmax):
    p = [0] * kmax
    result = []
    k = 0
    n = 2
    while k < kmax:
        i = 0
        while i < k and n % p[i] <> 0:
            i = i + 1
        if i == k:
            p[k] = n
            k = k + 1
            result.append(n)
        n = n + 1
    return result
(B) (A)で作成したスクリプトを primes1.pyxという名前で保存し、Cythonで拡張モジュール primes1 を作成せよ。必要な setup.py ファイルは以下の通りである。また、primes1.primes(1000) の処理時間を測定し、Python版とのパフォーマンスの違いについて考察せよ。
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [Extension("prime1", ["primes1.pyx"])]
setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = ext_modules
)
(C) primes1.pyx を以下のように変更して primes1.primes(1000) の処理時間を測定し、(B)との違いについて考察せよ。
cdef extern from "stdlib.h":
    ctypedef unsigned long size_t
    void *malloc(size_t size)
    void free(void *ptr)

def primes(int kmax):
    cdef int n, k, i
    cdef long *p

    p = <long*>malloc(sizeof(long)*kmax)
    if not p:
        raise MemoryError()
    try:
        result = []
        k = 0
        n = 2
        while k < kmax:
            i = 0
            while i < k and n % p[i] <> 0:
                i = i + 1
            if i == k:
                p[k] = n
                k = k + 1
                result.append(n)
            n = n + 1
    finally:
        free(p)
    return result

演習2 - 型定義

(A) 以下のスクリプトを bitset.pyx というファイル名で保存し、 拡張モジュール bitset を作成せよ。また、 BitSet(0x55).setflag(range(10000))の処理速度を測定せよ。
class BitSet:
    def __init__(self, flag):
        self.flag = flag

    def _setbit(self, n):
        return n | self.flag

    def setflag(self, nums):
        ret = []
        for n in nums:
            ret.append(self._setbit(n))
        return ret
(B) bitset.pyx を以下のように変更して BitSet(0x55).setflag(range(10000))の処理速度を測定し、 (A) との違いについて考察せよ。
cdef class BitSet:
    cdef int flag
    def __init__(self, flag):
        self.flag = flag

    cdef int _setbit(self, int n):
        return n | self.flag

    def setflag(self, nums):
        ret = []
        for n in nums:
            ret.append(self._setbit(n))
        return ret


Cython 演習問題 解説 へ続く