pythonでGPGPUやってみる
pythonでPyOpenclでGPGPUをやってみたいと思います。
PyOpenclはpythonでOpenCLを操作できるライブラリです。 OpenCLとはヘテロジニアス環境のためのフレームワークです。
今回は行列積をCPU(numpy.dot)とGPUでの演算時間を比較してみます。 今回はメモリ転送などの時間は考慮せずに単純に演算時間のみで比較したいと思ってます。
PC | CPU | Memory |
---|---|---|
macbook air 2012 | Intel core i5 | 4 GB |
# -*- coding: utf-8 -*- import numpy from numpy import linalg import time import pyopencl from pyopencl import mem_flags # size = 1024 for size in range(100,2000, 300): print "matrix : ", size, " x ", size a = numpy.random.randint(0, 256, (size,size)).astype(numpy.int32) b = numpy.random.randint(0, 256, (size,size)).astype(numpy.int32) dest = numpy.empty_like(a) start = time.time() dest1 = numpy.dot(a, b) end = time.time() print "compute with CPU (numpy) : ", end - start , " sec" dest1 = numpy.empty_like(a) context = pyopencl.create_some_context(interactive=False) queue = pyopencl.CommandQueue(context) a_buf = pyopencl.Buffer(context, mem_flags.READ_ONLY | mem_flags.COPY_HOST_PTR, hostbuf=a) b_buf = pyopencl.Buffer(context, mem_flags.READ_ONLY | mem_flags.COPY_HOST_PTR, hostbuf=b) dest_buf = pyopencl.Buffer(context, mem_flags.WRITE_ONLY, dest1.nbytes) program = pyopencl.Program(context, ''' __kernel void matrix_mul( __global const int* a, __global const int* b, __global int* dest, const int n ) { const int i = get_global_id(0); const int j = get_global_id(1); const int dest_index = j * n + i; dest[dest_index] = 0; for(int k = 0; k < n; k++){ dest[dest_index] += a[j * n + k] * b[k * n + i]; } } ''').build() n = numpy.int32(size) # カーネル関数にスカラー値を渡すにはnumpyの型を使う start = time.time() e = program.matrix_mul(queue, a.shape, None, a_buf, b_buf, dest_buf, n) e.wait() stop = time.time() pyopencl.enqueue_copy(queue, dest1, dest_buf) print "compute with GPGPU : ", stop - start, " sec"
実装結果
行列積 | CPU(numpy) | GPU |
---|---|---|
100 x 100 | 0.000992059707642 | 0.000531911849976 |
400 x 400 | 0.0700681209564 | 0.0166277885437 |
700 x 700 | 0.587120056152 | 0.298397064209 |
1000 x 1000 | 8.99130797386 | 1.30098700523 |
1300 x 1300 | 21.1716349125 | 2.89547991753 |
1600 x 1600 | 40.0069048405 | 5.48878097534 |
1900 x 1900 | 64.19876194 | 9.76343679428 |
やはりGPUは早いみたいです。 ただメモリ転送の部分がクリティカルパスになるというお話を聞いたので今後実験してみたいと思います。