のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

PythonとC++速度比較(1)配列っぽいものを作ろう。append,vector,array,matrix,list編

Sponsored Links

皆さんこんにちわ
お元気ですか?私はお酒飲みたいです。

Pythonで書いたコードがあるのですが、実行時間が遅すぎて結果がかえってこないのです。
このコードどうすれば速くなるかを考えました。

Pythonの部分をC++で書き直すだけでも速くなるはず…
C++Pythonで比較してみた。
ちなみに結果帰ってこないコードがどんなコードだったのかといいますと簡単にかくとこんな感じ。
厳密にいうと違いますがイメージです。

list = []
for i in xrange(100000):
    list2 = []
    for j in xrange(100000):
        list2.append(j)
    list.append(list2)

実験

実験内容

C++Pythonでなんらかの配列に数値を代入するだけの簡単なお仕事です。
これらの速度を比較した。
ちなみに10000 * 10000回の代入

実験環境

OS:X 10.9.1
CPU:2.8GHz IntelCore i7
メモリ:16GB 1600MHz DDR3

実験対象

C++
  1. std::vectorに対して、push_backで追加する
  2. std::vectorに対して、resizeしてから代入する
  3. ublas::matrixに対して代入する
  4. 2次元配列に突っ込む
Python
  1. listにappend
  2. numpy.arrayに代入する
  3. リスト内包表記

結果

C++
実験内容 速度(秒)
1.vector,push_back 3.83
2.vector,resize 0.99
3.matrix 2.36
4.2次元配列 0.39
Python
実験内容 速度(秒)
1.list.append 11.189393
2.numpy.array 36.716818
3.リスト内包 4.887393

感想

C++ですら書き方によって差が出てしまう。
用途によって使い分けなければならない。
Python? こんなことをするようなコードであれば、やめたほうがいい。
これだけでも10倍違うんですか。そうですか…。

こういったことをやりたい部分だけC++で書くことをお勧めする。

おまけ

N = 100000の時
Pythonだとアプリケーションメモリーエラーで計測できなかった。
書き方の問題なのかなぁ…。

C++
実験内容 速度(秒)
1.vector,push_back 915.197
2.vector,resize 84.6002
3.matrix 14.255
4.2次元配列 3.06836

急にmatrixが強くなる。

Source Cord

C++
#include <vector>
#include <iostream>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
#define NDEBUG

using namespace std;
using namespace boost::numeric;

int N = 10000;
int arr[10000][10000];

//全てpush_backでの追加
void vector1(){
	clock_t start,end;
	vector<vector<int> > list;
	start = clock();

	for(int i = 0; i < N; i++){
		vector<int> list2;
		for(int j = 0; j < N; j++){
			list2.push_back(j);
		}
		list.push_back(list2);
	}
	end = clock();
	cout << (double)(end-start)/CLOCKS_PER_SEC << endl;
}

//resizeしてから要素にアクセスして代入
void vector2(){
	clock_t start,end;
	vector<vector<int> > list;
	start = clock();
	list.resize(N);
	for(int i = 0; i < N; i++){
		list[i].resize(N);
	}

	for(int i = 0; i < N; i++){
		for(int j = 0; j < N; j++){
			list[i][j] = i;
		}
	}
	end = clock();
	cout << (double)(end-start)/CLOCKS_PER_SEC << endl;
}

//ublasの行列 matrix型
void ublas_matrix(){
	clock_t start,end;
	start = clock();
	ublas::matrix<int> mat(N,N);
	for(int i = 0; i < N; i++){
		for(int j = 0; j < N; j++){
			mat(i,j) = i;
		}
	}
	end = clock();
	cout << (double)(end-start)/CLOCKS_PER_SEC << endl;
}

//普通の配列
void array(){
	clock_t start,end;
	start = clock();
	for(int i = 0; i < N; i++){
		for(int j = 0; j < N; j++){
			arr[i][j] = j;
		}
	}
	end = clock();
	cout << (double)(end-start)/CLOCKS_PER_SEC << endl;
}

int main(void){
	vector1();
	vector2();
	ublas_matrix();
	array();
}
Python
#coding:utf-8
import numpy as np
import time

def list_append():
	N = 10000
	list = []
	time1 = time.clock()
	for i in xrange(N):
		list2 = []
		for j in xrange(N):
			list2.append(j)
		list.append(list2)

	time2 = time.clock()
	print time2 - time1

def numpy_array():
	time1 = time.clock()
	arr = np.zeros(10000,10000)
	for i in xrange(N):
		for j in xrange(N):
			arr[i][j] = i;
	time2 = time.clock()
	print time2-time1

def inside_list():
	N = 10000
	NN = N * N 
	time1 = time.clock()
	arr = [[y for y in xrange(N)]  for x in xrange(N)]
	time2 = time.clock()
	print "amen"
	print time2 - time1

if __name__ == '__main__':
	list_append()
	numpy_array()
	inside_list()