私は現在、ディスクからストリーミングされているオーディオのピッチ検出のためのバルク処理アルゴリズムを書いています。シリアルストリーミングされたデータに対してほぼリアルタイムで実行されるように、アルゴリズムを強化しました。
理想的には、システムがリアルタイムよりもはるかに高速に動作し、リアルタイムデータを渡して、それほど遅れることなくピッチトラックデータを生成できるようにしたいと思います。
今、私が驚いたのは、データのシリアル処理が、非常に高速化できる場所であるということです。私はクアッドコアi7(8つのハードウェアスレッドを使用)で実行しているので、処理を複数のブロックに分散させることで速度を大幅に向上させることができるはずです。
それが進むにつれて、私は現在次のことをしています:
- ディスクからデータをストリーミング
- 分析したいウィンドウサイズになるまでデータをバッファリングします。
- データのウィンドウを処理します。
- データをnサンプル戻します(nはスライドさせたい量です(これは80msウィンドウで1ms戻ることができます!)
- すすぎ、繰り返します。
これで、ウィンドウができたら、そのデータを特定のスレッド作業バッファーに簡単にコピーできることに気付きました(また、結果が書き込まれるメモリの場所を提供します)。このようにして、スレッドプールが処理する最大7つのスレッド(データをポンプするためにスレッド8を開いたままにする)のスレッドに相当するデータを効果的にバッファリングできます。
オーディオの8番目のウィンドウを送信しようとすると、データを処理するためのスレッドが使用可能になるまでプールをブロックします。データの処理を常に7つのスレッドで実行し続けるという考えです。以前の経験から、これを行うことで約5倍の速度が得られると思います。
過去に私はC++で自分のタスクベースのシステムを作成しましたが、このシステムは完全に機能しますが、このアプリはC#で開発されています。C ++で低いオーバーヘッドで優れた並列処理を実現するために、優れたロックレスキューイングメカニズムの構築にかなりの時間を費やしました。
私は、C#の下で、誰かが私のためにこれを行うことで苦痛を取り除くことを望んでいました。しかし、うまくいくように見えるものは何も見つかりません。System.Threading.ThreadPoolを確認しましたが、現在実行中のスレッドの数を確認する方法がないようです。オーバーヘッドが法外に思えることは言うまでもありません。次に、既存の事前に割り当てられた構造(処理で重要)を再利用できず、作業項目を送信するたびに再作成する必要があるという大きな問題が発生します。これには、処理できるよりも速く作業を生成するという大きな欠点があります。そのため、本当に必要のない構造やワークスペースのセットアップに膨大な時間を浪費するだけでなく、メモリ使用量が制御不能になります。
その後、System.Threading.Tasksについて知りましたが、それも私が求めている機能を提供していないようです。
相互運用機能を介してC++タスクマネージャーを使用することもできたと思いますが、この時代には、誰かがすでに同様の設定を行っていると思いました。だから私は何かが欠けていますか?または、誰かがそのようなタスク管理エンジンへのリンクを私に提供できますか?