ライブラリの使用中に効率を上げることが難しいのはなぜですか?


10

小さなデータベース処理は、Python / Perl / ...スクリプトで簡単に取り組むことができます。このスクリプトは、言語自体のライブラリやユーティリティを使用します。ただし、パフォーマンスに関しては、C / C ++ /低水準言語に手を伸ばす傾向があります。コードをニーズに合わせて調整できる可能性が、これらの言語をBigDataにとって非常に魅力的なものにしているようです-メモリ管理、並列処理、ディスクアクセス、さらには低レベルの最適化(C / C ++レベルのアセンブリ構造による)までも。

もちろん、そのような一連の利点はコストなしでは得られません。コードを書くこと、そして時にはホイールを再発明することさえも、非常に高価で面倒なことです。利用できるライブラリはたくさんありますが、パフォーマンスを付与する必要があるときはいつでも、自分でコードを書く傾向があります。大規模なデータベースの処理中にライブラリを使用してパフォーマンスアサーションを無効にするもの何ですか?

たとえば、Webページを継続的にクロールし、収集されたデータを解析する起業家について考えてみましょう。スライディングウィンドウごとに、抽出されたデータに対して異なるデータマイニングアルゴリズムが実行されます。開発者は、利用可能なライブラリ/フレームワーク(クロール、テキスト処理、データマイニングなど)を使用しないのはなぜですか?すでに実装されているものを使用すると、プロセス全体のコーディングの負担が軽減されるだけでなく、時間を大幅に節約できます。

シングルショットで

  • 自分でコードを書くことがパフォーマンスの保証になるのは何ですか?
  • 高いパフォーマンスを保証する必要があるときに、フレームワーク/ライブラリに依存することが危険なのはなぜですか?

1
正確な質問を明確にできますか?多分あなたが考えているいくつかの可能な答えも役立つかもしれません。
アミールアリアクバリ2014年

@AmirAliAkbari SeanOwenが回答を投稿し、質問の具体性の欠如に気づきました。彼の投稿にコメントを追加しました。どうか、投稿の改善を提案してください-それ以外の場合は削除するつもりです。
ルーベンス

回答:


4

自分で何度もリライトゲームを行った後(そしてそれでもなお)、私の即座の反応は適応性でした。

フレームワークとライブラリには、標準的なタスク用の(おそらく絡み合う可能性がある)ルーチンの膨大な武器がありますが、それらのフレームワークプロパティは、(常に?)ショートカットを許可しないことがよくあります。実際、ほとんどのフレームワークには、基本的な機能のコアレイヤーが実装されている、ある種のコアインフラストラクチャがあります。より具体的な機能は、基本層を利用し、コアの周りの2番目の層に配置されます。

ここでショートカットとは、コアを使用せずに2番目のレイヤールーチンから別の2番目のレイヤールーチンに直接進むことを意味します。(私のドメインからの)典型的な例は、タイムスタンプです。ある種のタイムスタンプ付きのデータソースがあります。ここまでの作業は、データをネットワークから読み取ってコアに渡すだけで、他のコードでそれを楽しむことができます。

さて、あなたの業界は非常に正当な理由でデフォルトのタイムスタンプ形式を変更しています(私の場合、UNIX時間からGPS時間に変更されました)。フレームワークが業界固有でない限り、コアが時間のコア表現を変更しようとする可能性は非常に低いので、最終的にはほとんど必要なことを行うフレームワークを使用することになります。データにアクセスするたびに、最初に業界時間形式に変換する必要があります。また、データを変更するたびに、コアが適切であると考えるものに変換する必要があります。二重変換せずにソースからシンクにデータを直接引き渡す方法はありません。

これが手作りのフレームワークが素晴らしい場所であり、わずかな変更であり、現実世界をモデリングし直していますが、他のすべての(業界固有ではない)フレームワークにはパフォーマンス上の欠点があります。

時間が経つにつれて、現実世界とモデルとの間の不一致が増加します。既製のフレームワークを使用すると、すぐに次のような質問に直面するだろう:私は表現することができますどのようthisthatまたはメイクルーチンんかX/農産物を受け入れますY

これまでのところ、これはC / C ++に関するものではありませんでした。ただし、なんらかの理由でフレームワークを変更できない場合、つまり、データを1つの端から別の端に変換するために二重変換を行わなければならない場合は、通常、追加のオーバーヘッドを最小限に抑える方法を採用します。私の場合、TAI-> UTCまたはUTC-> TAIコンバーターは、未加工のC(またはFPGA)に任せるのが最善です。エレガンスはありませんし、問題を簡単にするような深遠なスマートデータ構造もありません。これは退屈なswitchステートメントにすぎません。コンパイラーがまさにそれを最適化するのが得意な言語を使用してみませんか?


1
+1それは私の投稿があまり明確ではなかった私のせいかもしれません。これはきっと私が探していた種類の答えです。ありがとう。
ルーベンス

7

パフォーマンスが問題になるときに、誰もがC / C ++に手を伸ばすとは思いません。

低レベルのコードを書くことの利点は、CPUサイクルを少なくすることです。しかし、私は、高水準の言語が低水準の言語を呼び出して、この価値の一部を得ることができることに注意します。PythonおよびJVM言語はこれを行うことができます。

たとえば、デスクトップでscikit-learnを使用しているデータサイエンティストは、非常に最適化されたネイティブルーチンを呼び出して、数値を計算しています。スピードのために新しいコードを書く意味はありません。

分散された「ビッグデータ」のコンテキストでは、データ転送、つまりネットワーク転送とI / Oのボトルネックがより一般的です。ネイティブコードは役に立ちません。役立つのは、同じコードを書いて高速に実行するのではなく、よりスマートなコードを書くことです。

高水準言語では、C / C ++よりも開発者の時間をかけて、より高度な分散アルゴリズムを実装できます。大規模な場合、より優れたデータ移動を備えたよりスマートなアルゴリズムは、ばかばかしいネイティブコードに勝ります。

また、通常、開発者の時間とバグにより、新しいハードウェアよりも負荷が高くなることは事実です。上級開発者の1年の時間は、20万ドルが完全に読み込まれる可能性があります。1年以上にわたって、何百ものサーバーに相当する計算時間を貸し出しています。ほとんどの場合、より多くのハードウェアを投入するのではなく、最適化の手間をかけることは意味がないかもしれません。

「許可」、「無効」、「アサート」に関するフォローアップが理解できません。


誤解してすみません。私の意図は、アプリケーションを制御することの重要性、およびこの制御がライブラリによってどのように緩和されるかについての回答を提示することでした。もちろん、それらについて考えることもできます(通常、pthreadを書き換えることはありません)が、データが変化した場合(ロード、スループットなど)、パフォーマンスを付与するためにlibソースにアクセスする必要がある場合があります。そして、はい、それは必ずしもC / C ++である必要はありません-それらは通常hpcのために選択された言語ですが。質問を削除してもいいですか、それとももっと具体的な質問に変更しますか?私はそれを改善するための提案を受け入れます。
ルーベンス

1
いいえ、問題ありません。必要に応じて、コメントの編集に質問の編集に反映できます。
Sean Owen

質問が意味をなしているかどうか確認してください。わかりやすくするために、小さなケースを追加しました。質問に考慮事項を追加したい場合は、自由に編集してください。
ルーベンス

4

私たちが知っているように、デジタルの世界では、同じ仕事をしたり、期待した結果を得る方法がたくさんあります。

そして、コードから生じる責任/リスクは開発者の肩にかかっています。

これは小さいですが、.NETの世界からの非常に便利な例だと思います。

そのため、多くの.NET開発者は、データのシリアル化で組み込みのBinaryReader-BinaryWriterを使用して、パフォーマンスを向上させたり、プロセスを制御したりしています。

これは、FrameWorkの組み込みBinaryWriterクラスのオーバーロードされたWriteメソッドの1つのCSharpソースコードです。

// Writes a boolean to this stream. A single byte is written to the stream
// with the value 0 representing false or the value 1 representing true.
// 
public virtual void Write(bool value) 
{
     //_buffer is a byte array which declared in ctor / init codes of the class
    _buffer = ((byte) (value? 1:0));

    //OutStream is the stream instance which BinaryWriter Writes the value(s) into it.
    OutStream.WriteByte(_buffer[0]);
}

ご覧のとおり、このメソッドは、_buffer変数に追加で割り当てることなく作成できます。

public virtual void Write(bool value) 
{
    OutStream.WriteByte((byte) (value ? 1 : 0));
}

割り当てなしで数ミリ秒を得ることができます。この数ミリ秒は「ほとんど何もない」として受け入れることができますが、何千もの書き込みがある場合(つまり、サーバープロセス内)はどうなりますか?

「少数」が2(ミリ秒)で、数千のインスタンスがたったの2.000だとしましょう。これは、処理時間が4秒長くなることを意味します。4秒後に戻ります。

引き続き.NETからサブジェクトし、MSDNのBCL-.NET Base Class Library-のソースコードを確認できる場合は、開発者が決定した多くのパフォーマンスの低下を確認できます。

BCLソースからのポイントのいずれか開発者がwhile()またはforeach()ループを使用することを決定したのは通常のことです。これにより、コードでより高速なfor()ループを実装できます。

この小さな利益により、総合的なパフォーマンスが得られます。

そしてBinaryWriter.Write()メソッドに戻ると..

実際には、_buffer実装への追加の割り当ては開発者の責任ではありません。

_bufferを使用せずに2番目のメソッドを実装することを決定したと仮定します。2番目のメソッドを使用して数千バイトをワイヤ経由で送信しようとすると(つまり、BLOBまたはCLOBデータのアップロード/ダウンロード)、一般的に失敗する可能性があります。接続が失われました。チェックや制御メカニズムなしですべてのデータを送信しようとするためです。接続が失われた場合、サーバーとクライアントの両方が送信されたデータが完了したかどうかを知ることはありません。

開発者が「安全を確保する」と決定した場合、通常、パフォーマンスコストは実装された「安全を確保する」メカニズムに依存することを意味します。

しかし、開発者が「リスクを冒してパフォーマンスを上げる」と決定した場合も、これは誤りではありません。「危険な」コーディングについていくつかの議論があるまでは。

そして、小さなメモとして:商用ライブラリの開発者は、コードがどこで使用されるのかわからないため、常に安全を心がけています。


4

プログラマーの観点から見ると、フレームワークがパフォーマンスを最優先事項とすることはめったにありません。ライブラリが広く活用される場合、人々が最も重視する可能性が高いのは、使いやすさ、柔軟性、および信頼性です。

パフォーマンスは通常、二次的な競争ライブラリで評価されます。「Xライブラリの方が高速なので、優れています。」それでも非常に頻繁に、それらのライブラリーは、最適化されたソリューションを、広く活用できるソリューションとトレードオフします。

任意のフレームワークを使用することにより、より高速なソリューションが存在するというリスクを本質的に負います。ほとんどの場合、より高速なソリューションが存在すると言ってもいいでしょう。

自分で何かを書くことは、パフォーマンスを保証するものではありませんが、自分が何をしているのかを知っていて、要件のセットがかなり限られている場合に役立ちます。

JSON解析などがその例です。JSONを参照可能なオブジェクトに、またはその逆に変換するさまざまな言語用のライブラリが100あります。CPUレジスタですべてを実行する1つの実装を知っています。他のすべてのパーサーよりもかなり高速ですが、非常に制限されており、その制限は、使用しているCPUによって異なります。

高性能な環境固有のJSONパーサーを構築するタスクは良い考えですか?尊敬されるライブラリを100のうち99回活用します。その1つの個別のインスタンスでは、数百の反復を掛けた数個の追加のCPUサイクルにより、開発にそれだけの価値があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.