Pythonが科学計算に優れている理由

数日前( 元のメモは2017年9月12日に公開されました。以下、翻訳者のコメント )、私はフィードでこのツイートに気付きました。









私はCで「まだ」プログラミングしています。 なんで? ヒント:パフォーマンスに関するものではありません。 構文解析でエッセイを書いた... Onwardに登場!

(オンワード!プログラミングとソフトウェアについての新しいアイデアやパラダイムについて議論することに専念するSPLASHカンファレンスの1つです。)







それは良い週末の読書のように思えた-それはそれでした。 著者による主な論点:C言語はシステム統合言語として卓越しています。これは、「外部」コード、つまり独立して、場合によってはアセンブラーまでの他の言語で記述されたコードと対話できるためです。 実際、Cは、データをバイトレベルで処理できる数少ないプログラミング言語の1つです。 ほとんどの「現代の」言語では、セキュリティの名のもとでこの相互作用が禁止されています。アクセスできるメモリはすべて、セキュアな言語ランタイムを使用して割り当てられたメモリです。 その結果、あなたは彼の閉じた宇宙に閉じ込められています。







システム統合は、間違いなくしばしば見落とされがちなソフトウェアを扱う上で重要な側面です。 そして、これは特に、固定された一連の機能を備えたアプリケーションソフトウェアがまれである科学コンピューティングに当てはまります。 科学的な問題を解決するには、多くのプログラムを特定の問題に非常に依存する全体に集めることが必要になることがよくありますが、たぶん数回しか起動しません(このトピックに関する以前の投稿も参照してください)。 これは、システム統合が行うタスクです。必要に応じてリンクコードを使用して、断片から単一の全体を組み立てます。 計算科学では、ミドルウェアはスクリプト、ワークフロー、そして最近ではノートブックの形を取ります。 技術的な観点から、これはStephen Kellが参照するオペレーティングシステムのレベルでのシステム統合とは著しく異なりますが、機能的には同じです。







Stephenの記事は、パフォーマンスが低い言語としての評判にもかかわらず、Pythonが科学計算でこれほど成功している理由についてブログに書くという長年の計画を思い出しました。 だから...そこに彼女がいます。







もちろん、Pythonの成功には多くの理由がありますが、その1つは、システム統合のタスクに対処できることです。 Pythonには、この問題で重要だと思われる2つの機能があり、他の多くの言語ではサポートされていません。 1つは、インターフェイス用に明示的に設計されたデータ型です。 もう1つは、 ダックタイピングと、小さいながらも柔軟な標準インターフェイスのセットです。







科学計算のコンテキストでリンクするために設計された最初のPythonデータ型は、1995年にその前身であるNumericによって導入されたNumPyよりも古い、古くからあるNumPy配列です。 配列は、Fortran 77やAPLなどの言語で使用できる唯一のタイプである限り、科学計算の基本であるデータの1つのタイプです。 数値配列の実装は、Fortran Cと同じデータレイアウトで使用するように設計されており、1995年に科学計算を支配していたFortranおよびCライブラリとの相互運用を可能にします) 数値、そしてその後、NumPyは常に、FortranとCライブラリの接続言語としてPythonを使用し、タイムクリティカルな操作をこれらの言語で記述されたコードに委任することで速度を達成するという考えを持ちました。







バインディング用に設計された2番目のPythonデータ型は、 バッファプロトコルに関連付けられたmemoryview です 。 ここで、PythonはC字型メモリアクセスに最も近くなります。 バッファプロトコルを使用すると、さまざまなタイプのPythonデータがバイトレベルで相互の内部にアクセスできます。 典型的なユースケースは、配列データ型(例: Pillow )であり、配列型(例:NumPy)を介してメモリ内の画像表現にアクセスできます。これにより、配列の操作の形式で画像を操作するアルゴリズムを実装できます。







3番目の、最もよく知られていないバインディング用のPythonデータ型は、以前のCObjectを置き換えるcapsule です 。 カプセルは、ミドルウェア自体が何らかの方法でデータを検証または処理できない場合でも、Pythonミドルウェアを使用して互いに不透明なデータを交換できる、Cで記述されたPythonモジュールの利点のためにのみ存在します。 典型的な例は、PythonオブジェクトのC関数へのポインターをラップして、接続するPythonコード-たとえばスクリプト-が1つのモジュールから別のモジュールのCコードにC関数を転送できるようにすることです。







これらのインターフェイスデータ型はすべてPythonとCコードの間の仲介者ですが、多くの場合、PythonのシステムインテグレーターはCコードの使用を完全に認識していません。 Pythonのもう1つのシステム統合機能である標準インターフェイスでのダックタイピングは、独立して記述されたPythonモジュールのリンクを容易にします。 「標準インターフェイス」とは、シーケンス(シーケンス)とディクショナリ(ディクショナリ)のインターフェイス、および演算子のオーバーロードの標準メソッド名を意味します。







この機能が重要である理由を理解するために、意図的に欠落している静的に型付けされた言語を見てみましょう。 具体的な例として、Java多次元配列を取り上げます。 それらは言語や標準ライブラリの一部ではありませんが、合理的な努力でそれらの上に実装できます。 実際、選択可能なJava実装がいくつかあります。 これが問題です。 配列「A」の実装に基づく高速フーリエ変換(FFT)のライブラリと、配列「B」の実装に基づく線形代数のライブラリを使用するとします。 運が悪い-「A」と「B」の配列は異なるタイプであるため、FFT出力を線形方程式を解くためのシステムへの入力として使用することはできません。 基礎となる抽象化が同じであっても、実装に多くの共通点があっても問題ありません。 Javaコンパイラの場合、型は一致しません。それがポイントです。







Pythonはこの問題から完全に解放されているわけではありません。 入力として正確なデータ型を期待するPythonコードまたはCモジュールのコードを記述することは完全に可能です。そうでない場合は例外をスローします。 しかし、Pythonコードの場合、これはスタイルが悪いと見なされます。また、Python Cモジュールでも、パフォーマンスまたは他のCコードとの互換性が必要なものを除きます。 可能な場合、Pythonプログラマは標準のデータインターフェイスを使用することが期待されています。 たとえば、配列とインラインリストの反復とインデックス作成は同じように機能します。 標準インターフェイスでサポートされていない操作の場合、PythonプログラマーはPythonメソッドを使用することが期待されます。 実際には、独立して実装されたPython型は、独立して実装されたJava型よりもはるかに相互運用可能です。 n次元配列の特定のケースでは、Pythonには、技術的な問題ではなく社会的および歴史的な問題に関連する統一された実装の圧倒的多数採用のチャンスがありました。







最後に、Pythonは科学コンピューティングのシステム統合に非常に適していますが、もちろん制限があります。スティーブンケルがエッセイで説明している種類:Pythonコードと他の言語のコードとマネージメモリの組み合わせ、RまたはJuliaは多くの作業を必要としますが、その後も脆弱なままです。文書化されていない実装の詳細に基づいたトリックが必要だからです。 唯一の解決策は、ガベージコレクションをサポートし、オペレーティングシステムレベルのサービスとして提供される言語中立なデータオブジェクトの外観であり、バイトレベルでの管理されていない(管理されていない)アクセスの可能性を保持していると思われます、C 私が知っている最も近い既存の技術は、Microsoft CLRであり 、.NETという商品名でよく知られています。 現在、その実装はオープンソースであり、多くのプラットフォームで動作しますが、その起源は「Windowsのみ」であり、巨大なMicrosoftライブラリへの強力なリンクは、従来のUnix中心のコミュニティで科学コンピューティングに関わる人々の受け入れに対する障害となります。








All Articles