配列が大きい場合は、明らかに時間がかかります。すべてを調べる必要があります。
最初に行うことは、2 バイトから 1 バイトへのルックアップ テーブルを作成することです。そのため、次の 2 バイトを取得してオフセットを検索し、結果のバイトを取得します。
このルックアップ テーブルには 2^12 エントリ (最上位バイトから 4 バイトだけが必要) があり、CPU の L1 キャッシュにうまく収まる必要があります。shift-and-or よりも速いかもしれません。
一方、一度に 8 バイトをロードする場合 (現在はすべて 64 ビット CPU で)、それを 4 バイトに変換して格納できます。これを並列化できます (配列を 4 つの部分に分割し、各コアが 1 つの部分を処理するようにします)。
64 ビット レジスタからバイト 0、2、4、および 6 を取得し、それらを 32 ビット レジスタに格納する命令があれば、完了です。
更新:質問で、数百万バイトあると述べました。その場合は、気にしないでください。高度に最適化されたアセンブリと C での単純な実装との違いは、問題に値するものではありません。一度に 2 バイトずつデータをロードし、2 ニブルを 1 バイトにシフトして、ターゲット配列に格納するだけです。1MB のデータの処理は瞬時に行われるべきです。