標準の数値アルゴリズムにライブラリを使用しないのは一般的ですか?


54

GSLのような科学計算ライブラリでは、多くの数値アルゴリズム(積分、微分、補間、特殊関数など)を利用できます。しかし、これらの関数の「手巻き」実装を使用したコードをよく目にします。必ずしも一般に配布することを目的としない小さなプログラムの場合、計算科学者の間では、必要なときに数値アルゴリズム(Webサイト、数値レシピなどからコピーまたは転記すること)を自分で実装するのが一般的ですか?もしそうなら、GSLのようなものへのリンクを避ける特別な理由がありますか、それとも他のものよりも単なる「伝統」ですか?

私はコードの再利用が大好きなので、可能な場合は既存の実装を使用することをお勧めします。しかし、科学的な計算では一般的なプログラミングよりも原理の価値が低いという理由があるのではないかと思っています。


言及するのを忘れました:ライブラリの使用に明確な利点(実行速度)があるPythonのような言語とは対照的に、CとC ++について具体的に尋ねています。


14
一方では、車輪の再発明を望まないでしょう。一方、アルゴリズムを理解するための最良の方法(および拡張により、アルゴリズムが劇的に失敗する場合を簡単に診断する)は、実装を自分でコーディングすることです。
JM

2
出くわすすべての定理を非難しますか?たぶん、あなたはそれを試して、いくつかの赤ちゃんのケースをいじくり回しますが、それがあなたの研究の焦点でない限り、あなたはおそらくそれを受け入れて、人生を続けます。
DLS

3
物理学者はプログラマーではなく、他の人のコードを扱う(読むか修正する)ことに慣れていません。彼らが他の人のコードを使用しなければならないとき、それは他の物理学者によって書かれたコードやコメントがあまり上手く書かれていないことがよくあります。これは少なくとも一部の分野/コミュニティでは当てはまりますが、若者の間では態度が変化しています。しかし、すべてが悪いわけではありません。CSの学生が、簡単なライブラリを見つけられない場合、何もできないという態度を考えてください。
ザボルクス

回答:


45

私はすべてを自分で実装していましたが、最近はもっと多くのライブラリを使用し始めました。ライブラリを使用することには、ルーチンを自分で作成する必要があるかどうかの問題だけでなく、いくつかの非常に重要な利点があると思います。ライブラリを使用すると、

  • 何百/何千/それ以上のユーザーによってテストされたコード
  • ユーザーの作業なしで、今後も更新および改善され続けるコード
  • 最初の試行で記述するよりも効率的で、おそらくスケーラブルな最適化されたコード
  • ライブラリによっては、コード内でライブラリへのインターフェイスを確立することにより、現在使用していないが将来的に使用したい多くのアルゴリズムにアクセスできる場合があります

上記の最後の箇条書きで、私はTrilinosPETScのような大きなライブラリを考えています。PyClawの開発におけるいくつかの具体的な個人的な例でこれを強化できます。ClawpackをMPI呼び出しと並列することは簡単でしたが、PETScの使用を選択しました。これにより、パッケージ内のパラレコードを300行未満のPythonに制限できましたが、さらに良いことに、データをPETScの形式にすると、PETScの暗黙的なソルバーにすぐにアクセスでき、PyClawの暗黙的なソルバーで現在の作業が可能になりました。2番目の例として、PyClawには最初にハンドコードの5次WENO再構築が含まれていましたが、最終的にはPyWENOに依存することにしましたこのためのパッケージ。PyWENOは複数の言語で任意の順序のWENOルーチンを自動的に生成できるため、これは大きなメリットでした。

最後に、ライブラリを使用する場合、改善を開発するかバグを見つけることで貢献することができます。これは他の多くの人々に利益をもたらしますが、独自のコードのデバッグや改善はあなただけに利益をもたらします。


5
「改善を開発したり、バグを見つけることで貢献できます。これは他の多くの人々に利益をもたらします。」-それは、「いじくり回す/学ぶ」衝動と怠lazの両方を満たします(すでに行われたことをする必要はありません)。:)
JM

1
エッジケースも参照してください。多くのアルゴリズムでは、「機能する」ものを実装するのは簡単ですが、ケースの小さなサブフラクションを正しく処理しません。これは1回限りの小さなプロジェクトでは大丈夫かもしれませんが、自分が「最適化」したものの病的状態にひっかかった回数を数えることはできません。
meawoppl

34

ライブラリ関数へのリンクには、特にそのライブラリがプログラマにとって新しいものである場合、かなりのプログラマのオーバーヘッドがあります。多くの場合、特定のライブラリの詳細を把握するよりも、単純なアルゴリズムを書き換える方が簡単です。アルゴリズムがより複雑になると、この動作が切り替わります。

Pythonは、pip / easy_installなどのツールと均一なデータ構造インターフェイス(つまり、すべてのライブラリがnumpy配列を取得して生成するようです)により、このオーバーヘッドを削減することに優れています。


19

私が現在携わっているプロジェクトの1つは、粒子物理学検出器のクラス用の柔軟なシミュレーションおよび分析パッケージを作成することです。このプロジェクトの目標の一つは、提供することです今後数十年にわたって、これらのものに使用するコードベースを。

この時点ですでに20個以上の依存関係があり、ビルドプロセスが悪夢となり、信頼できるツールチェーンを提供するためだけに、Fermilabコンピューティングセンターから管理される別のプロジェクトが生まれました。

今、あなたがそのツールチェーンにないツールの必要性に遭遇したと想像してください(先月私に起こりました)。3つの選択肢があります

  1. あなたが所有しています。すべてのリスクと手間がかかります。
  2. ライブラリからコードをスクレイプし、プロジェクトに向けてコードを含めます。つまり、今後メンテナンスを行う必要があり、その場合は他の人のコードを理解する必要があります。
  3. ツールチェーンを維持している人々に行き、必要なものを頼み、リリースサイクルがそれを手に入れるのを待ちます。これらの人はかなり反応が良いですが、コードを動作させずに、または(1)または(2)を実行した後に、そのことを主張しなければなりません。

選択するのは非常に簡単です(1)。たぶん簡単です。


はい、追加された依存関係は、ライブラリを使用することの重大な欠点です。
デビッドケッチャソン

依存関係は、同様に私の心には大きな欠点である
媒介物

2
私の答えは、依存関係の事実を重視しすぎており、大規模プロジェクトにインストールされた依存関係の承認済み広告を取得する官僚的プロセスに十分ではない可能性があります。
dmckee

(nitpickのため申し訳ありません。)*ご使用中のポイント3
299792458

えー...いや それは私が意味することを言います。
dmckee

12

私はそれは考えている他より再実装される可能性が高いいくつかのアルゴリズムで、かなり一般的。

ライブラリのインストールの煩わしさ、アルゴリズムを自分で実装するのがどれだけ難しいか、最適化するのがどれほど難しいか、ライブラリがニーズにどれだけ適合するかということには、トリッキーなトレードオフがあります。また、ライブラリを使用するのがやり過ぎな場合もあります。プログラムの1つでスローバイセクションアルゴリズムを使用したのは、それを数回しか呼び出さず、そのためだけにライブラリを追加したくなかったからです。

最適化されたバージョンを書くのは簡単ですか?もしそうなら、あなたはそれをやったほうが良いかもしれません。必要なものを正確に取得し、誰の作業にも依存しません。しかし、もちろん、あなたは本当にあなたが何をしているのかを知る必要があります:単純なアルゴリズムでさえ、実装するのが難しい場合があります。

私はこれに関する研究に興味がありますが、私の偏見から、科学者はしばしば線形代数と乱数ジェネレーターのライブラリを使用し、残りのコードのほとんどは自家製です。


12
「もちろん、あなたは何をしているのかを本当に知る必要があります。単純なアルゴリズムでさえ、実装するのが難しい場合があります。」-これは十分に強調できません。
JM

10

ライブラリを使用する代わりにアルゴリズムを実装すると、モデルの理解と制御が向上する場合があると思います。科学計算用のプログラムをコーディングするとき、自分が何をしているかを理解することが重要です。重要なアルゴリズムを実装することで、問題についての知識を深め、問題をより適切に制御できるようになります。

一方、ソリューションを取得するために必要なライブラリを選択するのは簡単な作業ではない場合があります。そのため、何を達成しようとしているのか、なぜそれが必要なのかがわかっている場合は、既に実装されているアルゴリズムを検索する方が良いでしょう。

アルゴリズムが複雑な場合は、手作業でコーディングすることにより、タスク固有の機能を使用してソリューションのパフォーマンス/品質を向上させることができます。また、アルゴリズムを少し変更する必要がある場合があります。これは、作成したコードを知っていて、希望する方法で編集できる場合は簡単です。


1
理解を深めるために+1。ただし、これはライブラリルーチンの独自のアルゴリズムの問​​題です。
ファヒムミタ

8

1つの答えは、数値コードには非常に多くのわずかなバリエーションがあるため、それをライブラリにカプセル化するのは本当に難しいということです。多くの場合インストールが簡単で、入力と出力の明確なセットを備えたWebソフトウェアと比較して、これを考慮してください。より一般的なのは、フレームワーク、またはフレームワークのように振る舞う大きなライブラリ(Trilinos / PETSc)を手に入れ、そのエコシステムを使用してコミュニティコードを使用するメリットを得る人々だと思います。


7

ライブラリを使用するかどうかを決定する前に、ライブラリの使用がコードにどれだけ役立つかを把握したいと思うと思います。主要な計算カーネルに最適化されたライブラリを使用する場合、独自のライブラリを作成するよりもはるかに効率的です。

ただし、プログラムの実行中に1回だけ呼び出される特殊なルーチンを作成している場合、ライブラリに必要なフレームワークに適合するようにコードを調整する価値はありません。

(別のことを考えてみてください:ライブラリを活用するためにどのくらいの再設計が必要ですか?コードを修正するために費やす工数が、効率または数値精度の対応する利得によって補償されない限り、理想的には、これは最初にデータ構造とアルゴリズムを設計するときに計画するものであり、ライブラリの「フロー」が最初から考慮されるようにすることが理想的です。)


6

私の2セント。

C / C ++だけでなく、一般的にこれについて書く方が簡単だと思います。まず、Pythonのような言語のライブラリは、たとえそれが結果であっても、必ずしも速度のメリットを得るために使用されるわけではありません。@Davidはその理由をかなりよくカバーしていたと思います 。

言語の実装は、上から見た場合、どのライブラリにアクセスできるかをある程度決定します。計算科学で一般的に使用される言語には、C、C ++、Python、Perl、Java、Fortran、およびRが含まれます。あまり一般的ではない例として、OcamlおよびCommon Lispがあります。現在、これらの言語のほとんどはCで記述されているため、Cに対する自然な外部関数インターフェイス備えています。ただし、PythonからPerlライブラリを呼び出したり、その逆を行うのはそれほど簡単ではありません。そのため、実際には人々は

  1. 実装言語で書かれたライブラリを使用します。通常は標準ライブラリの一部であるか、そうでなければ広く利用可能なものです。

  2. 言語FFIを介してC / C ++ライブラリを呼び出します。これは、ラッパーが存在する場合、(1)と簡単に区別できないため、ラッパーがまだ存在しないことを前提としています。

(2)C / C ++関数を自分でラップする必要があるため、通常はより困難です。また、ライブラリをバンドルするか、依存関係を追加する必要があります。そのため、たとえばCにあるGSLを使用するよりも、組み込み言語ライブラリを使用する可能性が高くなります。

分布からランダムサンプルを生成する、または積分の求積法のような基本的な数値ルーチンなど、非常に汎用的なルーチンの場合、ライブラリを再利用するのは簡単で一般的です。実装しようとしている機能がより複雑になると、別のライブラリで必要な正確な関数を見つけることは指数関数的に不可能になります。必要です(たとえば、コードのスタイル/設計が問題になる場合があります)。また、上記で説明したように、そこにあるライブラリのサブセットのみにアクセスできます。一方で、アルゴリズムが複雑で主な焦点ではない場合、アルゴリズムを自分で実装するのは困難な場合があり、もちろんそれらの厄介な速度の問題に対処する必要があります。

したがって、これはコスト/利益分析の最適化問題になります。私の経験では、MCMCのような比較的標準的な手法であっても、ソフトウェア全体の設計方法により適しているため、通常は独自のコードを書くことになります。

もちろん、コードを使用しなくても、他の人のコードから学ぶことは可能です。しかし、科学者が実際にこれを行う頻度を知りません。私の印象では、他の人のコードを読んで学ぶことは、ソフトウェアエンジニアのことです。


6

私の2年目のメカニックコースを振り返ると、よく知られているアルゴリズムの独自のバージョンを実装した理由の一部は、そのように教えられたからだと思います。私は、学部生の物理教育で図書館とインターフェイスをとってリンクする方法を教えられた単一の例を考えることはできません。FORTRANの結合ニュートン方程式の解を自分で計算して、回転するゴルフボールの座標のリストを初めて見るのが大好きです。ゼロから物事を計算することから来る特定のスリルと満足感(プライドさえ)があります。


1
これは確かに要因です。そして、それを自分自身で行うことに焦点を当てることは、計算科学者の教育の一部に必要です。純粋なプログラマーはある時点でそれをノックアウトしますが、私たちの科学の種類は、その入門クラスから、同じルートに沿って来た他の人々によってほぼ独占的に予測された人口に移動するかもしれません。
dmckee

5

テスト済みのライブラリを可能な限り使用する必要があると思います。ほとんどの人は数値計算の専門家ではなく、十分にテストされたライブラリで利用できるものほど正確かつ慎重にソリューションを実装することはおそらくできないでしょう。ただし、特定のアプリケーションに必要な機能の組み合わせを実装する利用可能なライブラリがない場合もあります。これは、私が働いている技術分野で見られました。既存のコードはすべてのケースを解決するわけではなく、誰かがソルバーをゼロから実装することになりました。


1
ライブラリがニーズをすべてカバーしていない場合は、ライブラリコードを拡張してパッチを提出することをお勧めします。そうすれば、他の多くの人があなたの仕事で利益を得ることができ、他の人もあなたのためにコードをテストできます。もちろん、これはライブラリコードが十分に柔軟な方法で記述されており、ニーズに合わせて拡張できることを前提としています。
デビッドケッチャソン

私は同意します、それは素晴らしい解決策であり、可能な限り人々がすべきことです。
ムッカ2011

5

基本的な問題は、多くの場合、アプリケーションとライブラリの間のインターフェースにあります。アプリケーションプログラマーは、問題を(マトリックスとして)ライブラリに渡すときにしばしば失われる問題についての知識を持っています。この知識は、高度に最適化されたライブラリを使用する利点を相殺する以上のものです。その結果、アプリケーションプログラマは、知識を活用する独自の実装を「ロール」します。

したがって、本当に優れたライブラリーは、そのような知識をアプリケーションからライブラリーに渡す必要があります。そのため、ライブラリーもそれを利用できます。


3

すでに上記で述べたことすべてに加えて、「Fortran vs C ++」の質問からの答えを繰り返します。プログラマーが持っている最も貴重な資産は彼女の時間です。はい、外部依存関係はしばしば厄介です。しかし、他の人が既に実装しているアルゴリズムの再実装、デバッグ、テストに時間を費やすことはほとんど常に愚かであり、特定のトピックの専門家によって書かれたコードほど良い結果になることはめったにありません。他の人がやったことを再利用してください!


私はこのトピックについて自分の答えをします。すべての詳細を書き直すと、さらに多くを学ぶことができます。私は現在5〜6年間、点群で働いています。最初の3年間は、すべての機能を自分で書きました。後半は、ポイントクラウドライブラリの使用に費やしました。証明することはできませんが、最初の3年間を他の人がすでに提供しているソリューションについて考えることに費やしたことで、PCLの専門家であると思います。
ヤンハッケンバーグ

@JanHackenberg-ええ、しかし鈍くさせてください:車輪の再発明で3年間無駄にしただけです。他の人がやったことを使っていたら、どれだけ新しいことができたのか想像してみてください!?
ヴォルフガングバンガース

私は最初のphdの年にJavaで書くことにしました。この時点で、プログラミングスキル(情報学の理論ではない)をゼロに近いと考えていたからです。Javaは今でも私が実践するのに最適な言語でした。また、マルチプラットフォームを簡単にサポートできるため、Javaも適切な選択肢だと考えました。私はphd(伝統的な林業)で情報のない支持なしで椅子に入った。私は自分の間違いに気付いたときにc ++にジャンプしました(以前ではなく、公開後に)。
ヤンハッケンバーグ

ところで私は私の人生の3年を広めることに同意しません。これは、博士後期博士課程で2年しか役に立たなかったことを意味します。今日、私は100億個のシリンダーを林業の点群に適合させ、機械にどちらが樹木を表現するのに適しているかを判断させることができます。私の最大50人のユーザーも同様にできます。〜1時間で。大変で時間のかかる方法を学ぶことで学んだすべてのトリック。私は決してviの使い方を学ぶことはしないと決めましたが、必要な学習曲線を渡す人がコードを生成する最も効率的な方法を使うと主張するとき、彼らを信じます。
ヤンハッケンバーグ

2

私が働いているグループは、可能な限りライブラリを使用しています。私は数少ないプログラマーの一人で、残りの人々は仕事でプログラミングを始めました。彼らは自分の限界を十分に知っており、手を出してはならない場所を知っています。IMSLは優先ライブラリです。GSLのようなものは、これが連邦政府機関であり、とにかくソフトウェアを提供しているにもかかわらず、ライセンスの制限により禁止されます。


2

「再利用は主に社会的現象です。他の誰かのソフトウェアを使用できます。

  1. できます
  2. わかりやすい
  3. 共存できる
  4. サポートされています(または、私は自分でサポートしたいと思いますが、ほとんどサポートしていません)
  5. 経済的です
  6. 見つけることができます。

「— B. Stroustrup、The C ++ Programming Language 2 ed。(1991)p。383。


1

ライブラリを使用したり、独自のルーチンをローリングしたりするために、他の人からいくつかの正当な理由が与えられました。

ライブラリルーチンがカバーする広範囲の値や、それらのルーチンが提供する精度は必要ないことを事前に知っているため、特定のアプリケーションの計算を高速化できる場合があります。

もちろん、多くは特定のアプリケーションとライブラリルーチンが呼び出される回数に依存します。小さいxの範囲で少数の有効数字のみが必要な場合、ベッセル関数のライブラリルーチンを何十億回も呼び出すのはなぜですか?


0

追加することはほとんどありません。コードを再利用する必要があります。コードの持続可能性と社会への貢献に関するものですが、それはすべて上記です。

私たちがコードを再利用しない理由は、あなたがプログラマーを始めている場合、他のコードを理解するのが難しいからです。高度なC ++では特に難しく、純粋なCでもいくつかのトリックを行うことができます。

最初はメソッドをよく理解していますが、ライブラリに実装されている方法や、一般的なインターフェイス、エラー制御、および規則を使用してライブラリを使用する方法ではなく、経験豊富なプログラマーのために文書化されています。これは、LU分解などの標準的な方法を自分で実装する方が良いと錯覚します。さらに、新しいプログラマは、さまざまなオペレーティングシステムのコードテスト、検証、移植性の価値を過小評価しています。そのため、最後の理由は怠であり、独自のコードを書くことは、より高速で簡単なソリューションのように見えます。

現実には、自分でプログラミングするよりも、コードを使用して読むことでゼロから学ぶことができます。

怠azineはほとんどの時間私を駆り立てます、私も大多数の人だと思います。同じ理由で、最初からコードを書く人もいれば、既存のライブラリを使用する人もいます。


-1

ライブラリアルゴリズムは、独自の実装とは対照的に提供します。

  • それらは汎用でテンプレート化されています。多くの制約があるはずの独自のコードを変更することを心配することなく、後で実装を再パラメータ化できます。
  • 入力データの保存ケースと縮退ケースがあります。凸包アルゴリズムなどの多くの計算ジオメトリアルゴリズムは、たとえば3点の共線性を処理する必要があります。コードを配布する予定がなく、将来も頻繁にコードを再利用したくない場合は、これらのケースを無視できる場合があります。
  • これらは、予想される構成または最悪の場合の入力構成に対して、最小限の実行時の複雑さを提供します。より高いレベルのアルゴリズムは、レンガを構築する際に、多くの場合、より低いレベルのアルゴリズム、たとえばソートアルゴリズム、または特別なデータタイプを持ちます。クイックソートは、データをソートするための最も一般的な選択肢かもしれませんが、アルゴリズムの実装がn(log(n))を保証する必要がある場合、それを使用することはできません。
  • メモリ使用効率が高い
  • さらにランタイムが最適化されています
  • サポートされている場合、特にmainブランチで作業している場合は、一般的に「バグ」のないようにはるかに閉じられています。十分に分散されたライブラリほどテストされているものはありません。すべてのバグがクラッシュするわけではなく、すべてのバグが不合理な結果を生み出すわけでもありません。アルゴリズムの実装は、設計どおりではなく、許容できる結果を生成する可能性があります。バグが目立たないほど、一人の人間としてもそれを検出できる可能性は低くなります。

新しいフィールドに入力して、十分に理解可能なアルゴリズムの1つのバージョンを自分で実装するとき、私はまだ良いと思います。合計で多くの時間がかかります。Press et alという名前の本を買って読んだ。これらの実装の前後に、常に多くの理論を読みました。そして、フィールドの一般的な概念を理解し、実際にトラップを実際に経験した後、すべての面でより良いライブラリー実装にジャンプします。自分でライブラリフィールドに「hello world」アルゴリズムを記述した場合、ライブラリの優れたユーザーになると思います。

より大きなチームで作業する場合、チームが特定のライブラリを使用しているかどうかにかかわらず、自分で選択することはできません。コアチームが決定を行う場合があります。また、独自の時間計画を使用して、プロジェクトのライブラリバインドを担当する担当者が存在する場合があります。他の人の決定に依存することなく、独自の時間計画で実行できる1つのアルゴリズムを書き換えます。

あなたが一人でいて配布したい場合、別の問題があります。他の多くのソースコードと同様に、最も有用なリソースであると考えています。多くのすべての情報学者がここで同意するかもしれません。情報学以外の応用分野では、Windowsでプリコンパイルされた実行可能ファイルを提供する必要がある場合があります。Linuxでは、オープンソースの使用ライブラリの場合、比較的簡単に設定できます。

自分でアルゴリズムを書き換えると、ライセンスの自由が与えられます。たとえば、プロジェクトがGSLのGPLライセンスをサポートしてない場合があります。

ライセンスは、研究者の観点から独立した唯一の制約かもしれません。


1
「自分でアルゴリズムを実装する」と「ライブラリ構文を学習する」とは「同じ費用がかかる」と考えるのはばかげています。これは、「strcat」などの単純な関数にも当てはまりません。LAPACKにあるものや、より高いレベルのライブラリにあるものにはほとんど間違いありません。
ヴォルフガングバンガース

@WolfgangBangerthフィードバックをありがとう。私は自分が書いたものを読み直しましたが、自分の実装が実行可能であるというメッセージを転送したくありませんでした。しかし、私は多くを学びました。私の「両方とも2週間かかる」は良い例ではありませんでした。実際、フォームJavaをC ++に切り替えた2週間前に「構文を学ぶ」のに時間がかかりました。また、この時点で基本的なC ++構文も学びました。私は新しいライブラリーではなく、ポインターでさらに苦労しました。私が実装したアルゴリズムのいずれかで2週間はコーディング時間であったかもしれませんが、それは私の小さな投資でした(以前の本を読むのはもっと時間がかかりました)。
ヤンハッケンバーグ

投資は小さなアルゴリズム自体を書くことではありません。これは高速であり、実際には別のライブラリを学習するのに時間がかかる場合があります。信じられないほど多くの時間を費やすのは、物事をデバッグし、すべてのコーナーケースを正しくすることです。十分に開発されたライブラリを使用する場合、行列ベクトル積が正方行列で機能する場合、長方形行列でも機能することを知っています。独自のソフトウェアの場合は、関数を使い終わったと思っていても、これを実装してデバッグすることができます。同じ機能に何度も戻ります。それには時間がかかります。
ウォルフガングバンガース

@WolfgangBangerth私はあなたのすべての議論に同意します。私の唯一のポイントは、これらのコーナーケースを自分で処理する必要があるときに、より多くの理論を学ぶことです。私の答えの私の最初のバージョンは、実際には違いがないように聞こえました。私はひどく疲れていました。ライブラリの安定性の利点については、改善された回答で詳しく説明します。私にとっては、費やした時間と獲得した知識のトレードオフです。
ヤンハッケンバーグ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.