はじめに
はじめまして、ハーツテクノロジーの山口です。
今回はC++やC#など各言語の理解を深めるために、同僚のJamesさんが2019年に書いた記事[2019年の後半。いま、高速で生産性の高い開発言語はなに?!旬の言語 C++, C#, Javascript, Python で比較してみた!]を2021年12月の環境で比較をしました。
実行環境
- CPU: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz 2.30 GHz
- RAM: 16.0 GB (15.8 GB 使用可能)
- OS : Windows 10 Pro
今回比較対象としたのは以下の言語です。
- C++ / MinGW(v8.1.0)
- C# / Visual Studio 2022
- Javascript / node.js(v16.13.1)
- Python / Python(v3.8.2)
C++には最適化オプションを付けて実行しています。
コードについて
参考にした記事と同じく、ライプニッツの公式を使用し円周率を求めます。ライプニッツの公式は以下の通りに表されます。
今回は実行速度を比べるためシンプルにdoubleで計算するコードを書き計測しました。
C++
#include <stdio.h>
#include <time.h>
int main()
{
printf( "start\n" );
double limit = 10;
for (int i = 0; i < 10; i++) {
auto begin = clock();
double l = 0.0;
for (double n = 1; n < limit; n += 4)
{
l += (1.0 / n) - (1.0 / (n + 2));
}
printf("%1.16f", l * 4);
printf(" %f sec.\n", (double)(clock() - begin) / CLOCKS_PER_SEC);
limit *= 10;
}
printf("end\n");
return 0;
}
実行
> gcc -O3 CppProj.cpp
> CppProj
実行結果
C#
using System;
namespace CsProj
{
class Program
{
public static void Main()
{
System.Console.WriteLine("start");
double limit = 10;
for (int i = 0; i < 10; i++) {
System.DateTime begin = System.DateTime.Now;
double l = 0.0;
for (double n = 1.0; n < limit; n += 4)
{
l += (1.0 / n) - (1.0 / (n + 2));
}
System.Console.WriteLine("{0} {1}sec", l * 4, System.DateTime.Now.Subtract(begin).TotalMilliseconds / 1000);
limit *= 10;
}
System.Console.WriteLine("end");
}
}
}
実行結果
Javascript
console.log( 'start' )
let limit = 10
for (let i = 0; i < 10; i++) {
const begin = performance.now()
let l = 0.0
for (let n=1; n < limit; n += 4){
l += (1.0 / n) - (1.0 / (n + 2))
}
console.log( l * 4 , `${ ( performance.now() - begin ) / 1000 } sec.` )
limit *= 10
}
console.log("end")
実行
> node JsProj.js
実行結果
python
import time
print( "start" )
limit = 10
for m in range(0, 11):
begin = time.time()
n = 1
l = 0.0
while n < limit:
l += (1.0 / n) - (1.0 / (n + 2))
n += 4
print( l * 4, time.time() - begin, " sec." )
limit *= 10
print( "end" )
実行
> python PyProj.py
実行結果
Pythonを使用して1e10桁の計算は時間がかかるため結果が出ませんでした。
計測結果
計測結果から、Javascriptが一番早く計算が終わり、次にC++,C#の順に計算が終わり、最長がPythonでした。
Pythonはインタプリタ言語なので、コンパイラ言語のC++とC#、JITコンパイラのJavascriptに比べて非常に計算が遅いです。
Pythonについて追加検証
Pythonの実行結果が他の言語と比べて実行速度がとびぬけて遅い為、PyPyを使用して改善を試みました。
PyPyはPythonのコードをJITコンパイラで実行するため、実行速度を改善出来る見込みがあります。
コードはPythonの物と同じものを使用して実行しました。
- PyPy 7.3.7 with MSC v.1929 64 bit
PyPy
import time
print( "start" )
limit = 10
for i in range(0, 11):
begin = time.time()
n = 1
l = 0.0
while n < limit:
l += (1.0 / n) - (1.0 / (n + 2))
n += 4
print( l * 4, time.time() - begin, " sec." )
limit *= 10
print( "end" )
実行
> pypypre PyProj.py
実行結果
Pythonと比べて、数十倍の速度を改善しました。しかしJavascriptやC#,C++と比べると遅いです。
原因はPythonのFor文にあるのではないかと思いました。Pythonの計算ではライブラリのNumPyを使用してベクトル化することが多いため、NumPyで計算することでさらに改善できるのではないかと思います
今回は比較対象にC#やC++などがあり、比較が正しくできないと判断したため今回は検証しませんでした。
まとめ
結果から見てJITコンパイラのJavascriptがC++やC#よりも計算が早く出来たことが新たな発見でした。
Pythonはインタプリタ言語なので計算速度は遅いのですが、NumPyやPyPyなどコードの書き方や実行環境を整えれば実行速度の改善は出来そうです。