プログラミング言語の「速度」を決定するものは何ですか?


38

プログラムが2つの異なる言語で記述されているとします。それらを言語Xと言語Yとします。コンパイラーが同じバイトコードを生成する場合、なぜ言語Yの代わりに言語Xを使用する必要がありますか?1つの言語が他の言語よりも高速であることを定義するものは何ですか?

「Cが最も速い言語であり、ATSはCと同じくらい速い言語である」というようなことを人々がよく目にするので、これを尋ねます。プログラミング言語の「高速」の定義を理解しようとしていました。


21
あるプログラムが別のプログラムよりも高速である場合、同じバイトコードを持つことはできません。
svick

5
言語はプログラムを作成するために使用する概念であるため、実際に言語の速度について話すことはできません。
-Juho

1
@Raphaelトピックから外れていて、不明瞭で、あまりにも広すぎると感じています。このトピックはソフトウェアエンジニアリングにより適していますが、「広すぎる」として閉じられると思われます。
デビッドリチャービー

2
実装は別として、「速度」はあいまいであり、実装、コンパイル、実行、およびデバッグの速度は異なります。一般的に、他のものと引き換えになります(そうでなければすべてプログラミング言語を使用ます)
Nick T

上記のように。言語は同じバイトコードを生成しません。一部の言語は、バイトコードに簡単に解析できます。抽象化のレベルが高いものもあります。
超高輝度

回答:


23

プログラムの読みやすさ、プログラミングの容易さ、多くのプラットフォームへの移植性、優れたプログラミング環境の存在などが、言語Yよりも言語Xを選択する理由として考えられる多くの理由があります。ただし、質問で要求されている実行速度のみを考慮します。質問は、たとえば開発の速度を考慮していないようです。

2つの言語は同じバイトコードにコンパイルできますが、同じコードが生成されるわけではありません。

実際、バイトコードは特定の仮想マシンのコードのみです。エンジニアリング上の利点はありますが、特定のハードウェア向けに直接コンパイルする場合と根本的な違いはありません。したがって、同じマシン上で直接実行するためにコンパイルされた2つの言語を比較することも検討してください。

これは、言語の相対的な速度の問題は最初のコンパイラにさかのぼる古い問題であると言いました。

長年にわたり、専門家は手書きのコードはコンパイルされたコードよりも高速であると考えていました。つまり、機械語は、CobolやFortranなどの高レベル言語よりも高速であると見なされていました。そして、それはより速く、通常はより小さくなった。高レベル言語は、コンピューター科学者ではない多くの人々にとってはるかに使いやすいため、依然として開発されました。高級言語を使用するコストにも名前がありました:生成されたコードのサイズ(当時は非常に重要な問題)または実際に実行された命令の数に関係する拡張率。コンセプトは主に実験的なものでしたが、現在の標準ではコンパイラーがかなり単純な仕事をしていたため、比率は最初は1を超えていました。

したがって、機械語は、Fortranよりも高速でした。

もちろん、コンパイラーがより高度になるにつれて、それは長年にわたって変化し、現在ではアセンブリー言語でのプログラミングは非常にまれになっています。ほとんどのアプリケーションでは、アセンブリ言語プログラムは、コンパイラーの最適化によって生成されたコードと十分に競合しません。

これは、重要な問題の1つが、対象となる言語で使用できるコンパイラの品質、ソースコードを分析し、それに応じて最適化する能力であることを示しています。

この機能は、コンパイラの作業を容易にするために、ソースの構造的および数学的な特性を強調するために、言語の機能にある程度依存する場合があります。例えば、言語は、コンパイラーが最適化の目的でこれらのプロパティを使用できるように、ユーザー定義関数の代数的プロパティに関するステートメントを含めることができます。

言語のプログラミングパラダイムが、実際のマシンであろうと仮想マシンであろうと、コードを解釈するマシンの機能に近い場合、コンパイルプロセスが簡単になるため、より良いコードを生成できます。

もう1つのポイントは、言語で実装されたパラダイムが、プログラムされている問題のタイプに近いかどうかです。特定のプログラミングパラダイムに特化したプログラミング言語は、そのパラダイムに関連する機能を非常に効率的にコンパイルすることが期待されます。したがって、プログラミング言語の選択は、明快さと速度のために、プログラムされる問題の種類に適合したプログラミング言語の選択に依存する場合がある。

システムプログラミングでのCの人気は、おそらくCがマシンアーキテクチャに近く、システムプログラミングもそのアーキテクチャに直接関係しているという事実によるものです。

ロジックプログラミングと制約解決言語を使用して実行を高速化することにより、他の問題をより簡単にプログラミングできます。

複雑なリアクティブシステムは、そのようなシステムに関する非常に専門的な知識を具体化し、非常に高速なコードを生成するEsterelのような特殊な同期プログラミング言語で非常に効率的にプログラムできます。

または極端な例を挙げると、パーサーのプログラミングに使用される構文記述言語など、一部の言語は高度に専門化されています。パーサジェネレータは何もなく、そのような言語用のコンパイラではありません。もちろん、チューリング完全ではありませんが、これらのコンパイラーは、その専門性、つまり効率的な解析プログラムの作成に非常に適しています。知識の領域が制限されているため、最適化手法は非常に特殊化され、非常に細かく調整できます。これらのパーサージェネレーターは、通常、別の言語でコードを記述することで得られるものよりもはるかに優れています。制限されたクラスの問題に対して優れた高速のコードを生成するコンパイラーを備えた多くの高度に専門化された言語があります。

したがって、大規模なシステムを作成する場合、単一の言語に依存するのではなく、システムのさまざまなコンポーネントに最適な言語を選択することをお勧めします。もちろん、これは互換性の問題を引き起こします。

しばしば重要な別のポイントは、単にプログラムされているトピックのための効率的なライブラリの存在です。

最後に、速度が唯一の基準ではなく、コードの安全性(不正な入力やシステムエラーに対する回復力など)、メモリの使用、プログラミングの容易さなどの他の基準と矛盾する場合があります)、オブジェクトコードサイズ、プログラムの保守性など

速度が常に最も重要なパラメーターとは限りません。また、平均的な複雑さや最悪のケースの複雑さなどの複雑さなど、さまざまな装いが必要になる場合もあります。また、小さなプログラムのような大規模なシステムでは、速度が重要な部分と、重要性の低い部分があります。そして、それを前もって決定することは必ずしも容易ではありません。


ありがとう。そのようなもの。探していました。主題の資料を見つけるのは困難でした。これは十分に明らかにしました。
ロドリゴヴァレンテ

@RodrigoAraújoValenteありがとう、この質問をご覧ください。過激派の見解は、言語Lのコンパイラーは、何もせずにプログラムのソースコードにLのインタープリターをバンドルするだけでよいということです。次に、バンドルの計算を最適化することにより、より良い結果を得ることができます(部分評価)。最適化すればするほど、言語は速くなります。問題は、最適化に役立つものは何ですか?回答には、専門分野に関する十分な知識、プログラマーの支援、高度な分析などが含まれます。
babou

「同じバイトコード」とは、「同じ種類の実行可能な表現」を意味すると推測しています。明らかに、同一の実行可能ファイルは同じ速度で実行されます(同じ実行システムを想定)。(おそらく情報/通信の観点からこれを見たでしょう。理論的には、プログラマーはプログラムとハードウェアに関するすべてを知ることができますが、言語はしばしば通信を制限し(変換が許可または有用なものを制限します)、コンパイラーは知らないかもしれませんマイクロアーキテクチャーの詳細:コンパイルとコンパイラーの開発は、開発とトレーニングに類似しています...
Paul A. Clayton

これにより、人間が一般的に得意とするもの(一般的なパターンを認識するなど)と、コンピュータが一般的に得意とするもの(記録や「算術」など)がわかります。さらに、多くの場合、ランタイム情報の通信はよりコンピューターに優しいです(プロファイルに基づく最適化により、プログラミング言語を介して通信される情報の不足を克服できます)。動的最適化は、人間のプログラマーにとっては実用的ではありません...
ポールA.クレイトン

(特定のハードウェアを対象とする熟練したプログラマーがすべてのソフトウェアをアセンブリで作成することでも同じことが言えますが、ソフトウェアが最適化されるまでに、ハードウェアが変更されるだけでなく、ソフトウェアは廃止されます。)
Paul A. Clayton

16

最終的にすべてがCPU *で実行されますが、異なる言語の間にはさまざまな違いがあります。下記は用例です。

解釈言語 Python、Ruby、Matlabなど、一部の言語はコンパイルされずに解釈されます。つまり、PythonおよびRubyコードはマシンコードにコンパイルされず、その場で解釈されます。PythonとRubyを仮想マシンにコンパイルすることが可能です(次のポイントを参照)。この質問も参照してください。さまざまな理由により、通常、解釈はコンパイルされたコードよりも遅くなります。解釈自体が遅くなるだけでなく、最適化も難しくなります。ただし、コードがライブラリ関数(Matlabの場合)にほとんどの時間を費やす場合、パフォーマンスは低下しません。

仮想マシン一部の言語はバイトコードにコンパイルされます。バイトコードは発明された「マシンコード」であり、これが解釈されます。典型的な例は、JavaとC#です。バイトコードはその場でマシンコードに変換できますが、おそらくコードの実行速度は遅くなります。Javaの場合、移植性のために仮想マシンが使用されます。C#の場合、セキュリティなどの他の懸念があるかもしれません。

オーバーヘッド一部の言語は、セキュリティと効率を犠牲にしています。たとえば、Pascalの一部のバージョンは、境界外の配列にアクセスしないことを確認します。C#コードは「管理」されており、これにはコストがかかります。もう1つの一般的な例は、ガベージコレクションです。これは、プログラマの時間を節約しますが、実際のメモリ管理ほど効率的ではありません。例外処理やオブジェクト指向プログラミングのサポートのためのインフラストラクチャなど、オーバーヘッドの他のソースがあります。

*実際、今日の高性能システムはGPUやFPGAでもコードを実行します。


それで、基本的にもっとパフォーマンスが必要な場合、コンパイルされた言語に行くべきですか?そして、パラダイムについて?OOPの代わりに機能を選択する理由がありますか?
ロドリゴヴァレンテ

ガベージコレクションに関する発言は少し単純化されています。割り当てられたメモリが使用されなくなった場合、常に静的に決定できるとは限りません。決定可能であっても、エラーを起こさずに決定することは非常に難しい場合があります。したがって、GCが必要な場合があり、多くの場合はより安全です(配列境界のチェックなど)。さらに、明示的なリリースと組み合わせることができます。
babou

@RodrigoAraújoValenteに依存します。安っぽいコードは、しばしば安っぽいコードにコンパイルされます。たぶん、コードあなたは Pythonで書くことができますが、実際に高速なコードよりもあなたが Cで書くことができます
ラファエル

nit:あなたがリンクした質問で説明されているように、Pythonは実際には「オンザフライ」と解釈されません:)
Eevee

解釈セクションで言及した言語は、その場で解釈されません。Pythonはバイトコードにコンパイルされ、RubyはASTにコンパイルされましたが、現在はバイトコードにコンパイルされていると思います。Matlab、私は実際にJITがコンパイルされたと信じています。実際、少なくとも何らかの仮想マシン表現にコンパイルするのではなく、その場で物事を解釈する非ニッチ言語の実装を知りません。
ウィンストンイーバート

5

Yの代わりにXを選択するには、次のようなさまざまな要因があります。

  • 学びやすさ
  • わかりやすさ
  • 開発のスピード
  • 正しいコードの実施を支援する
  • コンパイルされたコードのパフォーマンス
  • サポートされているプラ​​ットフォーム環境
  • 移植性
  • 目的に適う

C#やPythonなどのビジネスプロジェクトの開発に適した言語もありますが、C ++などのシステムプログラミングに適した言語もあります。

どのプラットフォームで作業するのか、どのアプリケーションを作成するのかを決定する必要があります。


1
では、コンパイルされたコードのパフォーマンスをどのように判断しますか?それが基本的に私にこの質問をさせた理由です。
ロドリゴヴァレンテ

6
この回答には確かに良いアドバイスがありますが、質問に対する回答がわかりません。これは、言語の選択要因としての速度に関するものです。
-babou

RodrigoAraújoValente@彼らもないかもしれないこと(あなたの言語が解釈されている場合)、コードをコンパイル。
ラファエル

1
「優れたライブラリ」と「優れたツール」を追加できます。
ラファエル

@RodrigoAraújoValente実行してプロファイルを作成します。
カイル

2

どのプラットフォームでも使用できる「最速」のプログラミング言語は、対象のチップセットのアセンブリ言語です。そのレベルでは翻訳はありません。ただし、チップセットがどのように命令を実行するか、特に並行して実行できる命令については、ある程度の知識が必要です。

Cからアセンブリへの変換は非常に「浅い」ため、1対1に近くなりますが、読みやすくなります。ただし、移植性を向上させるための標準ライブラリにより、その上に多くのレイヤーがあります。コンパイラがアセンブリコードを取得するために必要なことはそれほど多くありません。一般的に、マシン固有の変更を行うための強力な最適化があります。

C ++はより豊富な言語を追加します。ただし、言語は非常に複雑になるため、コンパイラがプラットフォームに最適なコードを作成するのが難しくなります。

次に、スケールの反対側に移動します。通訳言語。これらは、作業の実行に加えて、コードを解析してマシンコールに変換するのに時間がかかるため、最も遅い傾向があります。

それからそれらの間にあります。一般に、プラットフォームに最適化された仮想マシン層があります。そして、コンパイラーは、実行する仮想マシンのコードを作成します。これは、perl、pascal、ruby、Pythonのように一度にすべて発生することもあります。または、javaのようないくつかの段階で。

これらの仮想マシンの一部は、中間バイトコードを変換するのではなく、マシンレベルのコードを作成することにより、ランタイムを高速化するJITコンパイラの概念を追加します。

一部の仮想マシンは、バイトコードからマシンコードへの変換が少ない低レベルです。移植性を保ちながら物事を高速化します。


歴史的に、Cはマシンコードへの簡単な翻訳を可能にするように設計されていました。ただし、Cを効率的なCコードに変換するには、プログラマーが何をしようとしているかをコンパイラーが把握し、その意図をマシンコードに変換する必要があります。例えば、歴史的に、*p++=*q++;多くのマシンでのマシンコードに相当するものはより高速array1[i]=array2[i];でしたが、多くのプロセッサーでは逆の場合が多いため、コンパイラーは前者のコードを後者に変換することがあります-ほとんど「浅い」変換ではありません。
スーパーキャット

通常、これを行う-O0と最適化は行われません。最適化はコンパイラで得られるボーナスですが、言語自体は1対1でアセンブリに変換できます。
アルキメデストラハノ

2

まだ言及されていない点は、一部の言語では同じコードを何度も実行すると、常に同じアクションのシーケンスが実行されるということです。したがって、コンピューターは、コードのセクションが何をすべきかを一度決定するだけです。JavaScriptの「厳密な使用」方言の主な利点の1つは、JavaScriptエンジンがコードの一部を理解すると、次に実行されるときにその情報を利用できることです。「use strict」がなければ、できません。

たとえば、「use strict」がない場合、次のようなコードが含まれます。

function f() { return x; }

即時呼び出しコンテキストがある場合は変数Xを返すか、外部呼び出しコンテキストから変数Xを返すか、を返しUndefinedます。さらに悪いことに、次のようなループで:

for (i=0; i<40; i+=1) { g(i); }

JavaScriptエンジンg()は、i[またはgそれ自体で何を行うか]を知る方法がありません。以来gまたはi非常に合法的に変えることができるi文字列には、JavaScriptエンジンは、単純にどちらかの関数呼び出しのがに何をしたかどうかを確認するために、ループ内の数値の加算と数値比較を使用していますが、各パス上の必須ループチェックを通してすることはできませんiかループを通過するたびにそれらを検索する必要がなく、1回で済み、大幅な時間の節約になります。g。対照的に、「use strict」[やや健全]方言では、JavaSciptエンジンは上記のコードを調べて、ループを通過するたびに同じ数値変数を使用し、同じ関数を呼び出すことを知ることができます。したがって、識別iと機能のみが必要です。g


2

ここにはかなり専門的な答えがいくつかありますが、これはそれらに近いものではありませんが、あなたにとって直感的なものかもしれません。

できるだけ早くタスクを実行する必要がある場合、アセンブリで実行するコードを書きたいと何度も聞いたことがあるかもしれません。これは、タスクを完了するために実際に必要なコマンドのみを実行するためです。高レベル言語では、このタスクを数行で実装できますが、コンパイラーはそれらを機械語に翻訳する必要があります。この翻訳は、直接書くことができるため、必ずしも最小限のものではありません。これは、マシンがコマンドを実行するのに多くのクロックを費やすことを意味します。

コンパイラーは現在非常に洗練されていますが、最高のアセンブリー・プログラマーができるほど効果的ではありません。

この方向で続けると、これらの不必要なコマンドは、言語が高レベルになるにつれて(通常)量が増えます。(これはすべての高水準言語に100%当てはまるわけではありません)

したがって、特定のコードについて、XのマシンコードがYより短い場合、言語Xは言語Y(実行時)よりも高速です。


アセンブリは完全に揺れ動きます。しかし、最高のコンパイラよりも優れたパフォーマンスを発揮するには、真のアーティストが必要です。
ヨハン

1

この質問は非常に複雑で多次元的であるため(たとえば、自動車のブランドを雑多な基準で比較するようなものです)、この質問に明確に答えることは困難ですがRosettaコードとして知られる優れたコードリポジトリを含む新しい科学的研究があります(ウィキペディアの概要)。Nanz and Furiaによるこの2014年の調査では、次の典型的な基準と、典型的な主観的なコード品質のまれな定量分析に基づいて、この問題を極めて明確かつ科学的に研究しています。要約には、客観的に根拠のある所見と一般化が含まれています。(うまくいけば、これらの結果に基づいた他の研究が将来行われるかもしれません。)

  • RQ1。どのプログラミング言語がより簡潔なコードを作成しますか?

  • RQ2。どのプログラミング言語が小さな実行可能ファイルにコンパイルされますか?

  • RQ3。実行時のパフォーマンスが優れているプログラミング言語はどれですか?

  • RQ4。メモリをより効率的に使用するプログラミング言語はどれですか?

  • RQ5。失敗しにくいプログラミング言語はどれですか?

要約-プログラミング言語に関する議論は、科学的というよりも宗教的な場合があります。どの言語がより簡潔または効率的であるか、開発者の生産性を高めるかについての質問は熱心に議論され、彼らの答えは逸話と根拠のない信念に基づいていることが多すぎます。この調査では、さまざまな言語の一般的なプログラミングタスクのソリューションのコードリポジトリであるRosetta Codeの未開発の研究の可能性を活用し、分析用の大規模なデータセットを提供します。私たちの調査は、主要なプログラミングパラダイムを表す8つの広く使用されている言語(手順:CおよびGo、オブジェクト指向:C#およびJava、機能:F#およびHaskell、スクリプト:PythonおよびRuby)の745タスクに対応する7,087ソリューションプログラムに基づいています。統計分析により、最も注目すべきことは次のとおりです。関数型言語およびスクリプト言語は、手続き型言語およびオブジェクト指向言語よりも簡潔です。Cは、大規模な入力で生の速度を達成するのに勝るものはありませんが、中程度のサイズの入力に対するパフォーマンスの違いはそれほど顕著ではなく、インタープリター言語でさえ競争力があります。コンパイル時により多くの欠陥をキャッチできる、コンパイル済みの厳密に型指定された言語は、インタプリタ型または弱い型指定の言語よりも実行時エラーを起こしにくい。これらの結果が開発者、言語設計者、教育者に与える影響について説明します。コンパイル時により多くの欠陥をキャッチできる場合、インタープリタ型または弱い型付けの言語よりも実行時エラーが発生しにくくなります。これらの結果が開発者、言語設計者、教育者に与える影響について説明します。コンパイル時により多くの欠陥をキャッチできる場合、インタープリタ型または弱い型付けの言語よりも実行時エラーが発生しにくくなります。これらの結果が開発者、言語設計者、教育者に与える影響について説明します。


0

コンピューター言語は、コンピューターに何をすべきかを説明するためのコマンドの単なる抽象化です。

コンピューター言語で記述Pythonし、Cコンパイラー(cython)でコンパイルすることもできます。

これを念頭に置いて、コンピューター言語の速度を比較することはできません。

ただし、同じ言語のコンパイラをある程度まで比較できます。たとえば、GNU Cコンパイラ対Intel Cコンパイラ。(コンパイラベンチマークを検索)


2
質問についてコメントしたい場合は、回答ではなくコメントボックスを使用してください。これはComputer Science Stack Exchangeであり、文学がワープロではないように、コンピューターサイエンスはプログラミングではないことに注意してください。プログラミングに関する質問は、ソフトウェアエンジニアリングまたはスタックオーバーフローで行われます。
デビッドリチャービー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.