web-dev-qa-db-ja.com

C ++ forループが遅すぎる

PortAudioでオーディオアプリケーションを作成しようとしています。私のコールバック関数は非常に遅く、一定のアンダーランを引き起こしています。問題が見つかるまで、コールバックのすべてを1つずつ削除しました:forループ。すべてを削除して、コールバック関数で発生するのはforループだけであり、それでもアンダーランが発生するようにしました。反復回数を減らすとアンダーランがなくなるため、これはforループです。

static int patestCallback(const void *inputBuffer, void *outputBuffer,
                      unsigned long framesPerBuffer,
                      const PaStreamCallbackTimeInfo *timeInfo,
                      PaStreamCallbackFlags statusFlags, void *userData)
{
    int x = 0;
    for (int jj = 0; jj < 10000; jj++)
    {
        x++; // for testing, not actually used
    };
    return paContinue;
}

テスト用の私の完全なコードは次のとおりです: https://Gist.github.com/johnroper100/b87641f5609dbb49bc3c1121b1f4daf1

この質問には実際には必要ありませんが、python同等(サウンドデバイス))で同じコールバックを行いましたが、問題はありません。

1
John Roper

ループやプログラム全体の速度を低下させる可能性があるAPI固有の質問は別として、一般的な質問には一般的なアドバイスを提供します。戻り値を無視する場合は、常に接頭辞(++i;)よりも接頭辞(i++;)を優先します。これは、接頭辞が演算子を適用している値/オブジェクトのコピーを返さないためです。 。したがって、不要なコピー操作を回避できます。ただし、最新のコンパイラのほとんどはオンザフライでこれを置き換えますが、なんらかの方法でコードがだまされてしまう可能性があるため、常にプレフィックスのインクリメントを使用する習慣をつけるのが最善です。そしてもちろん、最高のパフォーマンスを得るには、-O3パラメータを使用してコードをコンパイルし、コンパイラが最善を尽くすことを確認する必要があります。ループをさらに最適化するために考慮すべきもう1つのオプションは、マルチスレッド化です。

0
Hack06

おそらく、patestCallbackの終了後に新しいフレームをキャプチャするコードが呼び出されます。期限に間に合わない場合は、CPUの能力が十分でない(=処理が複雑すぎる)ことを意味します。これは(理由の)説明ではありませんが、CPUに複数のコアがある場合に機能するはずのソリューション(コアが1つでも機能する場合があります)では、オーディオを処理するスレッドを作成できます。コールバックは、処理されるオーディオにのみコピー(またはポインターを変更)する必要があります。これにより、メインスレッド(オーディオキャプチャスレッド)が長時間待機しなくなります。

0
phoenixstudio