8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Matlabでは値渡しがデフォルトなので、書き方によってはものすごく遅くなる

Last updated at Posted at 2018-07-08

C++

C++において関数への引数の渡し方には値渡し、ポインタ渡し、参照渡しがあり、これらを適切に使い分けることでプログラムのパフォーマンス(速度やメモリ消費量等)をコントロールすることができます。
一般的には、インスタンスの生成・破棄コストが無視できるint/double等のプリミティブな型に対しては値渡しを、無視できないクラスのインスタンスに対しては参照渡しを使います。ポインタ渡しは仮想関数を呼び出すときに使うことが多いですが、一般的には生ポインタの代わりにunique_ptr, shared_ptr, weak_ptrを使うため、ポインタ渡しを使う場面はあまり多くないと思います。

参考:C++ Core Guidelines, F.call: Parameter passing

Python/MATLAB

一方、PythonやMATLABではC++の参照渡しを制御する&演算子に相当するキーワードが存在せず、デフォルトでどのように渡されるのかが決まっています。

Python

pythonでは、int/double等のプリミティブな型は値渡しでその他は参照渡しであり、C++でプログラミングする時と同じ使い分け方なのであまり気にすることなくプログラムを書くことができます。
@shiracamus さんの指摘の通り、上の表現は間違っていますので削除します。
Python言語リファレンスを読んだところ、immutable/mutableなオブジェクトについては3.1 オブジェクト、値、および型

すべての属性は、同一性 (identity)、型、値をもっています。 __同一性 は生成されたあとは変更されません。__これはオブジェクトのアドレスのようなものだと考えられるかもしれません。(中略)オブジェクトによっては 値 を変更することが可能です。値を変更できるオブジェクトのことを mutable と呼びます。生成後に値を変更できないオブジェクトのことを immutable と呼びます。

を、代入文については8.10. copy — 浅いコピーおよび深いコピー操作

Python において代入文はオブジェクトをコピーしません。代入はターゲットとオブジェクトの間に束縛を作ります。

が明快な説明でしょうか。名前の束縛については4.2.1. 名前の束縛を参照。

__名前 (name) は、オブジェクトを参照します。__名前を導入するには、名前への束縛 (name binding) 操作を行います。
以下の構造で、名前が束縛されます: 関数の仮引数 (formal parameter) 指定、 import 文、クラスや関数の定義 (定義を行ったブロックで、クラスや関数名を束縛します)、代入が行われるときの代入対象の識別子(後略)

名前の束縛=参照の値渡しということでしょうか。なるほど。

MATLAB

ところが__MATLABは基本的に値渡しです__(参照渡しをするにはハンドル型を継承する必要がある)。このため、MATLABで下手なコードを書くと著しくパフォーマンスが下がります。

追記:引数として関数に渡した変数を関数内で変更しない限りはコピーされません。変数を変更する場合コピーされます。

例えば、この春に他の学生がMATLABで書いた数値計算プログラムをC++に書き換えたのですが、約300倍高速になりました。
プロファイリングしてみると、私のC++プログラムにおいては計算時間の95%がソルバーの行列計算(Ax=bをxについて解く)で占められていたのですが、MATLABプログラムにおいてソルバーの行列計算(x = A\b)の占める割合は1%未満で、30%はメッシュファイルの出力、60%は行列要素の計算に費やされていました。

なぜ行列要素の計算にこれほどの時間が費やされていたかというと、その学生は巨大なモノリシックなクラスを定義してそのインスタンスを関数に渡していたため、関数を呼び出すたびにその巨大なクラスのインスタンスがコピーされていたからです。単一責任原則(SRP)に従ってクラス・関数を細かく分割してコードを書いていればここまで速度に差は出なかったと思います。

(日本ではMATLABを使ってプログラミングを勉強した人は少ないと思いますが、アメリカの大学では無料でMATLABを使えるところが多いため、MATLABでプログラムを勉強しそのまま使っている学生がたくさんいます。なので値渡し・参照渡し・ポインタ渡し自体を知らない学生がいます。)

8
10
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?