C言語

【C言語】第2章第14回:ループアンロールの基礎

ループアンロール(Loop Unrolling)は、ループ処理を効率化するための最適化手法です。この章では、その仕組みや適用例、注意点について学びます。

1. ループアンロールとは?

ループアンロールは、繰り返し処理を展開してコードを最適化するテクニックです。これにより、ループの反復回数を減らし、処理のオーバーヘッドを削減できます。

通常のループ構造

for (int i = 0; i < 4; i++) {
    array[i] = i * 2;
}

アンロール後の構造

array[0] = 0 * 2;
array[1] = 1 * 2;
array[2] = 2 * 2;
array[3] = 3 * 2;

アンロールされたコードは、ループ構造を持たないため、ループのオーバーヘッドを回避します。

2. 基本例:簡単なループのアンロール

以下のプログラムは、配列の要素を更新する通常のループとアンロールされたループの例を示します。

#include <stdio.h>

int main() {
    int array[4];

    // 通常のループ
    for (int i = 0; i < 4; i++) {
        array[i] = i * 2;
    }

    // アンロールされたループ
    array[0] = 0 * 2;
    array[1] = 1 * 2;
    array[2] = 2 * 2;
    array[3] = 3 * 2;

    for (int i = 0; i < 4; i++) {
        printf("array[%d] = %d\n", i, array[i]);
    }

    return 0;
}

解説:

  • 通常のループ:簡潔な記述が可能ですが、オーバーヘッドが発生します。
  • アンロール後:ループの処理が展開され、オーバーヘッドが削減されます。

3. 実用例:データ処理の最適化

アンロールは、大量のデータ処理で特に効果を発揮します。以下の例は、配列の合計値を計算するアンロールの実用例です。

#include <stdio.h>

int main() {
    int array[] = {1, 2, 3, 4, 5, 6, 7, 8};
    int sum = 0;

    // 通常のループ
    for (int i = 0; i < 8; i++) {
        sum += array[i];
    }

    printf("Sum (normal loop): %d\n", sum);

    // リセット
    sum = 0;

    // アンロールされたループ
    sum += array[0] + array[1];
    sum += array[2] + array[3];
    sum += array[4] + array[5];
    sum += array[6] + array[7];

    printf("Sum (unrolled loop): %d\n", sum);

    return 0;
}

解説:

  • 通常のループ:各要素を逐次加算。
  • アンロール後:2要素ずつまとめて処理し、加算回数を減少。

4. ループアンロールのメリットと注意点

**メリット**

  • ループのオーバーヘッドを削減。
  • パフォーマンスの向上(特に小規模ループ)。

**注意点**

  • コードが長くなり、可読性が低下する可能性があります。
  • 大規模なループでは効果が限定的。

5. 練習問題

以下の課題に挑戦して、ループアンロールの使い方を練習してください。

  1. 配列の各要素を2倍にするループをアンロールして最適化してください。
  2. 配列内の要素を合計する通常のループをアンロールし、処理回数を減らしてください。
  3. 文字列内の文字を順に出力するループをアンロールしてください。

6. 練習問題の解答と解説

問1の解答

#include <stdio.h>

int main() {
    int array[] = {1, 2, 3, 4};

    // アンロールされたループ
    array[0] *= 2;
    array[1] *= 2;
    array[2] *= 2;
    array[3] *= 2;

    for (int i = 0; i < 4; i++) {
        printf("array[%d] = %d\n", i, array[i]);
    }

    return 0;
}

問2の解答

#include <stdio.h>

int main() {
    int array[] = {1, 2, 3, 4, 5, 6};
    int sum = 0;

    // アンロールされたループ
    sum += array[0] + array[1];
    sum += array[2] + array[3];
    sum += array[4] + array[5];

    printf("Total sum: %d\n", sum);
    return 0;
}

問3の解答

#include <stdio.h>

int main() {
    char str[] = "Hello";

    // アンロールされたループ
    printf("%c", str[0]);
    printf("%c", str[1]);
    printf("%c", str[2]);
    printf("%c", str[3]);
    printf("%c\n", str[4]);

    return 0;
}

7. まとめ

ループアンロールは、特定の場面でパフォーマンスを向上させる効果的なテクニックです。ただし、適用範囲や可読性への影響を考慮しながら使用することが重要です。