본문 바로가기
Tech/Coding

에라스토테네스의 체 추가실험(로컬에서 실험)

by redcubes 2025. 2. 28.
import time
import array
import math
import matplotlib.pyplot as plt
import numpy as np


def sieve_segmented(n):
    """
    # 세그먼트 체 (Segmented Sieve)
    # 메모리 사용량과 캐시 효율을 높이기 위해 세그먼트 단위로 처리
    """
    if n < 2:
        return []

    limit = int(math.sqrt(n)) + 1
    base = [True] * (limit + 1)
    base[0:2] = [False, False]
    for i in range(2, int(math.sqrt(limit)) + 1):
        if base[i]:
            for j in range(i * i, limit + 1, i):
                base[j] = False
    base_primes = [i for i, is_prime in enumerate(base) if is_prime]

    segment_size = max(limit, 10000)
    primes = base_primes.copy()

    low = limit
    while low <= n:
        high = min(low + segment_size - 1, n)
        segment = [True] * (high - low + 1)
        for p in base_primes:
            start = ((low + p - 1) // p) * p
            if start < p * p:
                start = p * p
            for j in range(start, high + 1, p):
                segment[j - low] = False
        primes.extend([i for i, is_p in enumerate(segment, start=low) if is_p])
        low += segment_size
    return primes


def sieve_basic(n):
    """
    # 기본적인 에라토스테네스의 체 구현
    # 모든 배수를 확인하는 기본 방식
    """
    f = [0] * (n + 1)
    for i in range(2, n + 1):
        if f[i] == 1:
            continue
        for j in range(2 * i, n + 1, i):
            f[j] = 1
    primes = [i for i in range(2, n + 1) if f[i] == 0]
    return primes


def sieve_optimized(n):
    """
    # 최적화된 에라토스테네스의 체
    # 제곱근까지만 확인하고, i*i부터 시작하여 효율성 향상
    """
    f = [0] * (n + 1)
    for i in range(2, int(n ** 0.5) + 1):
        if f[i] == 0:
            for j in range(i * i, n + 1, i):
                f[j] = 1
    primes = [i for i in range(2, n + 1) if f[i] == 0]
    return primes


def sieve_bitwise(n):
    """
    # 비트 연산을 활용한 에라토스테네스의 체
    # 비트 단위로 표시하여 메모리 사용량 감소
    """
    word_size = 64
    f = [0] * ((n // word_size) + 1)

    def is_set(num):
        return (f[num // word_size] & (1 << (num % word_size))) != 0

    def set_bit(num):
        f[num // word_size] |= (1 << (num % word_size))

    for i in range(2, int(n ** 0.5) + 1):
        if not is_set(i):
            for j in range(i * i, n + 1, i):
                set_bit(j)
    primes = [i for i in range(2, n + 1) if not is_set(i)]
    return primes


def sieve_array(n):
    """
    # array 모듈을 사용한 에라토스테네스의 체
    # 메모리 효율성 향상을 위해 array 모듈 활용
    """
    f = array.array('b', [0] * (n + 1))
    for i in range(2, int(n ** 0.5) + 1):
        if f[i] == 0:
            for j in range(i * i, n + 1, i):
                f[j] = 1
    primes = [i for i in range(2, n + 1) if f[i] == 0]
    return primes


def sieve_wheel6(n):
    """
    # 6모듈러 휠 최적화 기법
    # 2와 3의 배수를 미리 제외하고 6k±1 형태의 숫자만 확인
    """
    MAX = n + 1
    LIM = int(n ** 0.5) + 1
    RSET = lambda start, end, gap: set(range(start, end, gap))

    # 5 (mod 6)와 1 (mod 6)에 해당하는 후보들 (단, 1은 소수가 아니므로 7부터)
    prime = RSET(5, MAX, 6) | RSET(7, MAX, 6)
    if n > 2:
        prime.add(3)
    if n > 1:
        prime.add(2)
    for i in range(5, LIM, 6):
        if i in prime:
            prime -= RSET(i * i, MAX, i * 6) | RSET(i * (i + 2), MAX, i * 6)
        j = i + 2
        if j in prime:
            prime -= RSET(j * j, MAX, j * 6) | RSET(j * (j + 4), MAX, j * 6)
    return sorted(list(prime))


def sieve_wheel30(n):
    """
    # 30모듈러 휠 최적화 기법
    # 2, 3, 5를 미리 제거한 후, 30의 배수에서 후보군(서로소인 숫자: 30k+1,7,11,13,17,19,23,29)만 대상으로 체 작업 수행
    """
    if n < 2:
        return []

    sieve = [False, False] + [True] * (n - 1)
    for p in (2, 3, 5):
        if p * p > n:
            break
        for i in range(p * p, n + 1, p):
            sieve[i] = False

    # 30의 배수에서 2,3,5를 제외한 후보군만 검사
    residues = (1, 7, 11, 13, 17, 19, 23, 29)
    for i in range(7, int(math.sqrt(n)) + 1):
        if sieve[i] and (i % 30 in residues):
            for j in range(i * i, n + 1, i):
                sieve[j] = False

    return [i for i, is_prime in enumerate(sieve) if is_prime]


def sieve_bytearray(n):
    """
    # bytearray를 활용한 에라토스테네스의 체
    # 메모리와 연산을 최적화하기 위해 bytearray 사용
    """
    if n < 2:
        return []

    sieve = bytearray(b'\x01') * (n + 1)
    sieve[0] = sieve[1] = 0
    for i in range(2, int(math.sqrt(n)) + 1):
        if sieve[i]:
            sieve[i * i:n + 1:i] = bytearray(len(sieve[i * i:n + 1:i]))
    return [i for i, is_prime in enumerate(sieve) if is_prime]


def sieve_extreme(n):
    """
    # 극도로 최적화된 에라토스테네스의 체
    # 휠 제거(2,3,5), 바이트 배열 사용, 세그먼트 처리를 모두 적용한 최적화 버전
    """
    if n < 2:
        return []

    # 작은 소수들 미리 처리 (2, 3, 5)
    small_primes = []
    if n >= 2:
        small_primes.append(2)
    if n >= 3:
        small_primes.append(3)
    if n >= 5:
        small_primes.append(5)

    # 30의 배수에서 소수 후보만 검사 (2, 3, 5와 서로소)
    residues = (1, 7, 11, 13, 17, 19, 23, 29)

    # 제곱근까지의 소수 찾기 (기본 세그먼트)
    limit = int(math.sqrt(n)) + 1
    base_sieve = bytearray(b'\x01') * (limit + 1)
    base_sieve[0] = base_sieve[1] = 0

    # 미리 찾은 소수의 배수 제거
    for p in (2, 3, 5):
        if p * p > limit:
            break
        for i in range(p * p, limit + 1, p):
            base_sieve[i] = 0

    # 30의 배수에서 소수 후보만 검사
    for i in range(7, int(math.sqrt(limit)) + 1):
        if base_sieve[i] and (i % 30 in residues):
            for j in range(i * i, limit + 1, i):
                base_sieve[j] = 0

    # 기본 세그먼트에서 소수 수집
    base_primes = small_primes + [i for i in range(7, limit + 1) if
                                  base_sieve[i] and (i % 30 in residues or i in small_primes)]

    # 세그먼트 처리
    segment_size = max(limit, 10_000)
    primes = base_primes.copy()

    low = limit
    while low <= n:
        high = min(low + segment_size - 1, n)
        segment = bytearray(b'\x01') * (high - low + 1)

        # 세그먼트에서 소수의 배수 제거
        for p in base_primes:
            start = max(p * p, ((low + p - 1) // p) * p)
            for j in range(start, high + 1, p):
                segment[j - low] = 0

        # 세그먼트에서 소수 수집 (30의 배수에서 소수 후보만)
        for i in range(low, high + 1):
            if segment[i - low] and (i % 30 in residues or i in small_primes):
                primes.append(i)

        low += segment_size

    return primes


def sieve_linear(n):
    """
    # 선형 체 (Linear Sieve, Euler's Sieve)
    # 각 수를 한 번씩만 처리하여 O(n) 시간 복잡도로 소수 판별
    # lp 배열은 각 수의 최소 소인수(lowest prime factor)를 저장
    """
    primes = []
    lp = [0] * (n + 1)
    for i in range(2, n + 1):
        if lp[i] == 0:
            lp[i] = i
            primes.append(i)
        for p in primes:
            if p > lp[i] or i * p > n:
                break
            lp[i * p] = p
    return primes


def run_benchmark(sizes):
    """
    주어진 크기마다 모든 알고리즘의 성능을 측정하는 함수
    """
    algorithms = [
        ("기본 체", sieve_basic),
        ("최적화 체", sieve_optimized),
        ("비트 체", sieve_bitwise),
        ("배열 체", sieve_array),
        ("6모듈러 체", sieve_wheel6),
        ("30모듈러 체", sieve_wheel30),
        ("바이트배열 체", sieve_bytearray),
        ("세그먼트 체", sieve_segmented),
        ("선형 체", sieve_linear)
    ]

    results = {name: {"sizes": [], "times": [], "prime_counts": []} for name, _ in algorithms}

    for size in sizes:
        print(f"\n크기 {size:,}에 대한 성능 측정 중...")

        for name, algorithm in algorithms:
            # 너무 큰 입력에 대해 기본 체는 실행하지 않음
            if name == "기본 체" and size > 500000:
                print(f"  {name}: 크기가 너무 커서 건너뜀")
                results[name]["sizes"].append(size)
                results[name]["times"].append(None)
                results[name]["prime_counts"].append(None)
                continue

            start_time = time.time()
            primes = algorithm(size)
            elapsed_time = time.time() - start_time

            print(f"  {name}: {len(primes):,}개 소수 찾음, {elapsed_time:.6f}초 소요")

            results[name]["sizes"].append(size)
            results[name]["times"].append(elapsed_time)
            results[name]["prime_counts"].append(len(primes))

    return results


def plot_results(results, save_path=None):
    """
    성능 측정 결과를 그래프로 시각화하는 함수
    """
    # 한글 폰트 문제 해결을 위해 영어로 레이블 변경
    plt.figure(figsize=(12, 8))

    # 선 스타일 및 색상 정의
    colors = plt.cm.tab10(np.linspace(0, 1, len(results)))
    markers = ['o', 's', '^', 'D', 'v', '<', '>', 'p', '*']

    # 알고리즘 이름 영어 매핑
    eng_names = {
        "기본 체": "Basic Sieve",
        "최적화 체": "Optimized Sieve",
        "비트 체": "Bitwise Sieve",
        "배열 체": "Array Sieve",
        "6모듈러 체": "Wheel-6 Sieve",
        "30모듈러 체": "Wheel-30 Sieve",
        "바이트배열 체": "Bytearray Sieve",
        "세그먼트 체": "Segmented Sieve",
        "선형 체": "Linear Sieve"
    }

    for i, (name, data) in enumerate(results.items()):
        valid_indices = [j for j, t in enumerate(data["times"]) if t is not None]
        if not valid_indices:
            continue

        valid_sizes = [data["sizes"][j] for j in valid_indices]
        valid_times = [data["times"][j] for j in valid_indices]

        plt.plot(
            valid_sizes,
            valid_times,
            marker=markers[i % len(markers)],
            linestyle='-',
            color=colors[i],
            label=eng_names.get(name, name)
        )

    plt.title('Prime Number Sieve Algorithms Performance', fontsize=16)
    plt.xlabel('Input Size (n)', fontsize=14)
    plt.ylabel('Execution Time (seconds)', fontsize=14)
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.legend(loc='upper left', fontsize=12)

    # 두 개의 그래프 생성: 로그 스케일과 일반 스케일
    plt.yscale('log')
    plt.xscale('log')
    if save_path:
        plt.savefig(f"{save_path}_log_scale.png", dpi=300, bbox_inches='tight')

    # 두 번째 그래프: 기본 체를 제외한 최적화된 알고리즘만 표시
    plt.figure(figsize=(12, 8))

    for i, (name, data) in enumerate(results.items()):
        if name == "기본 체":
            continue

        valid_indices = [j for j, t in enumerate(data["times"]) if t is not None]
        if not valid_indices:
            continue

        valid_sizes = [data["sizes"][j] for j in valid_indices]
        valid_times = [data["times"][j] for j in valid_indices]

        plt.plot(
            valid_sizes,
            valid_times,
            marker=markers[i % len(markers)],
            linestyle='-',
            color=colors[i],
            label=eng_names.get(name, name)
        )

    plt.title('Optimized Prime Number Sieve Algorithms (Basic Excluded)', fontsize=16)
    plt.xlabel('Input Size (n)', fontsize=14)
    plt.ylabel('Execution Time (seconds)', fontsize=14)
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.legend(loc='upper left', fontsize=12)

    if save_path:
        plt.savefig(f"{save_path}_optimized_only.png", dpi=300, bbox_inches='tight')

    plt.show()


def save_results_to_csv(results, filename):
    """
    성능 측정 결과를 CSV 파일로 저장하는 함수
    """
    import csv

    # 모든 알고리즘에 대한 크기 목록 통합
    all_sizes = set()
    for data in results.values():
        all_sizes.update(data["sizes"])
    all_sizes = sorted(all_sizes)

    with open(filename, 'w', newline='') as f:
        writer = csv.writer(f)

        # 헤더 행
        header = ['크기']
        for name in results.keys():
            header.append(f'{name} (시간)')
            header.append(f'{name} (소수 개수)')
        writer.writerow(header)

        # 데이터 행
        for size in all_sizes:
            row = [size]
            for name, data in results.items():
                try:
                    idx = data["sizes"].index(size)
                    row.append(data["times"][idx])
                    row.append(data["prime_counts"][idx])
                except ValueError:
                    row.append(None)
                    row.append(None)
            writer.writerow(row)

    print(f"결과가 {filename}에 저장되었습니다.")


if __name__ == '__main__':
    # 테스트할 입력 크기 목록
    test_sizes = [10000000*i for i in range(5,11)]

    # 성능 측정 실행
    print("소수 찾기, 알고리즘 성능 측정을 시작합니다...")

    # 알고리즘 목록 업데이트 - extreme 추가
    algorithms = [
        ("기본 체", sieve_basic),
        ("최적화 체", sieve_optimized),
        ("비트 체", sieve_bitwise),
        ("배열 체", sieve_array),
        ("6모듈러 체", sieve_wheel6),
        ("30모듈러 체", sieve_wheel30),
        ("바이트배열 체", sieve_bytearray),
        ("세그먼트 체", sieve_segmented),
        ("선형 체", sieve_linear),
        ("극한 최적화 체", sieve_extreme)  # 새로 추가한 알고리즘
    ]

    results = {name: {"sizes": [], "times": [], "prime_counts": []} for name, _ in algorithms}

    for size in test_sizes:
        print(f"\n크기 {size:,}에 대한 성능 측정 중...")

        for name, algorithm in algorithms:
            # 너무 큰 입력에 대해 기본 체는 실행하지 않음
            if ((name == "기본 체")or (name=="비트 체")) and size > 10000000000:
                print(f"  {name}: 크기가 너무 커서 건너뜀")
                results[name]["sizes"].append(size)
                results[name]["times"].append(None)
                results[name]["prime_counts"].append(None)
                continue

            start_time = time.time()
            try:
                primes = algorithm(size)
                elapsed_time = time.time() - start_time

                print(f"  {name}: {len(primes):,}개 소수 찾음, {elapsed_time:.6f}초 소요")

                results[name]["sizes"].append(size)
                results[name]["times"].append(elapsed_time)
                results[name]["prime_counts"].append(len(primes))
            except Exception as e:
                print(f"  {name}: 오류 발생 - {str(e)}")
                results[name]["sizes"].append(size)
                results[name]["times"].append(None)
                results[name]["prime_counts"].append(None)

    # 결과 저장
    save_results_to_csv(results, "sieve_benchmark_results.csv")

    # 영어 이름 매핑 업데이트
    eng_names = {
        "기본 체": "Basic Sieve",
        "최적화 체": "Optimized Sieve",
        "비트 체": "Bitwise Sieve",
        "배열 체": "Array Sieve",
        "6모듈러 체": "Wheel-6 Sieve",
        "30모듈러 체": "Wheel-30 Sieve",
        "바이트배열 체": "Bytearray Sieve",
        "세그먼트 체": "Segmented Sieve",
        "선형 체": "Linear Sieve",
        "극한 최적화 체": "Extreme Optimized Sieve"  # 새로 추가한 알고리즘
    }

    # 그래프 그리기
    print("\n그래프를 생성하는 중...")

    plt.figure(figsize=(12, 8))

    # 선 스타일 및 색상 정의
    colors = plt.cm.tab10(np.linspace(0, 1, len(results)))
    markers = ['o', 's', '^', 'D', 'v', '<', '>', 'p', '*', 'X']

    for i, (name, data) in enumerate(results.items()):
        valid_indices = [j for j, t in enumerate(data["times"]) if t is not None]
        if not valid_indices:
            continue

        valid_sizes = [data["sizes"][j] for j in valid_indices]
        valid_times = [data["times"][j] for j in valid_indices]

        plt.plot(
            valid_sizes,
            valid_times,
            marker=markers[i % len(markers)],
            linestyle='-',
            color=colors[i],
            label=eng_names.get(name, name)
        )

    plt.title('Prime Number Sieve Algorithms Performance', fontsize=16)
    plt.xlabel('Input Size (n)', fontsize=14)
    plt.ylabel('Execution Time (seconds)', fontsize=14)
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.legend(loc='upper left', fontsize=12)
    plt.yscale('log')
    plt.xscale('log')
    plt.savefig("sieve_performance_log_scale.png", dpi=300, bbox_inches='tight')

    # 두 번째 그래프: 기본 체를 제외한 최적화된 알고리즘만 표시
    plt.figure(figsize=(12, 8))

    for i, (name, data) in enumerate(results.items()):
        if name == "기본 체":
            continue

        valid_indices = [j for j, t in enumerate(data["times"]) if t is not None]
        if not valid_indices:
            continue

        valid_sizes = [data["sizes"][j] for j in valid_indices]
        valid_times = [data["times"][j] for j in valid_indices]

        plt.plot(
            valid_sizes,
            valid_times,
            marker=markers[i % len(markers)],
            linestyle='-',
            color=colors[i],
            label=eng_names.get(name, name)
        )

    plt.title('Optimized Prime Number Sieve Algorithms (Basic Excluded)', fontsize=16)
    plt.xlabel('Input Size (n)', fontsize=14)
    plt.ylabel('Execution Time (seconds)', fontsize=14)
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.legend(loc='upper left', fontsize=12)
    plt.savefig("sieve_performance_optimized_only.png", dpi=300, bbox_inches='tight')

    plt.show()

    print("\n벤치마크 완료!")
소수 찾기, 알고리즘 성능 측정을 시작합니다...

크기 50,000,000에 대한 성능 측정 중...
  기본 체: 3,001,134개 소수 찾음, 5.742000초 소요
  최적화 체: 3,001,134개 소수 찾음, 2.970000초 소요
  비트 체: 3,001,134개 소수 찾음, 14.197064초 소요
  배열 체: 3,001,134개 소수 찾음, 4.544533초 소요
  6모듈러 체: 3,001,134개 소수 찾음, 3.596000초 소요
  30모듈러 체: 3,001,134개 소수 찾음, 3.211000초 소요
  바이트배열 체: 3,001,134개 소수 찾음, 1.199001초 소요
  세그먼트 체: 3,001,134개 소수 찾음, 3.774999초 소요
  선형 체: 3,001,134개 소수 찾음, 5.035000초 소요
  극한 최적화 체: 3,001,134개 소수 찾음, 5.113000초 소요

크기 60,000,000에 대한 성능 측정 중...
  기본 체: 3,562,115개 소수 찾음, 6.886506초 소요
  최적화 체: 3,562,115개 소수 찾음, 3.621586초 소요
  비트 체: 3,562,115개 소수 찾음, 17.689013초 소요
  배열 체: 3,562,115개 소수 찾음, 5.512000초 소요
  6모듈러 체: 3,562,115개 소수 찾음, 4.186370초 소요
  30모듈러 체: 3,562,115개 소수 찾음, 3.935000초 소요
  바이트배열 체: 3,562,115개 소수 찾음, 1.496000초 소요
  세그먼트 체: 3,562,115개 소수 찾음, 4.532107초 소요
  선형 체: 3,562,115개 소수 찾음, 5.872053초 소요
  극한 최적화 체: 3,562,115개 소수 찾음, 6.034009초 소요

크기 70,000,000에 대한 성능 측정 중...
  기본 체: 4,118,064개 소수 찾음, 7.830284초 소요
  최적화 체: 4,118,064개 소수 찾음, 4.268781초 소요
  비트 체: 4,118,064개 소수 찾음, 20.019000초 소요
  배열 체: 4,118,064개 소수 찾음, 6.246681초 소요
  6모듈러 체: 4,118,064개 소수 찾음, 5.394999초 소요
  30모듈러 체: 4,118,064개 소수 찾음, 4.513014초 소요
  바이트배열 체: 4,118,064개 소수 찾음, 1.906999초 소요
  세그먼트 체: 4,118,064개 소수 찾음, 5.567000초 소요
  선형 체: 4,118,064개 소수 찾음, 7.069002초 소요
  극한 최적화 체: 4,118,064개 소수 찾음, 7.198506초 소요

크기 80,000,000에 대한 성능 측정 중...
  기본 체: 4,669,382개 소수 찾음, 9.459015초 소요
  최적화 체: 4,669,382개 소수 찾음, 4.910000초 소요
  비트 체: 4,669,382개 소수 찾음, 23.533762초 소요
  배열 체: 4,669,382개 소수 찾음, 7.173999초 소요
  6모듈러 체: 4,669,382개 소수 찾음, 6.205001초 소요
  30모듈러 체: 4,669,382개 소수 찾음, 5.179519초 소요
  바이트배열 체: 4,669,382개 소수 찾음, 2.066000초 소요
  세그먼트 체: 4,669,382개 소수 찾음, 6.261000초 소요
  선형 체: 4,669,382개 소수 찾음, 8.085001초 소요
  극한 최적화 체: 4,669,382개 소수 찾음, 8.686102초 소요

크기 90,000,000에 대한 성능 측정 중...
  기본 체: 5,216,954개 소수 찾음, 10.728039초 소요
  최적화 체: 5,216,954개 소수 찾음, 5.799975초 소요
  비트 체: 5,216,954개 소수 찾음, 27.162037초 소요
  배열 체: 5,216,954개 소수 찾음, 8.266024초 소요
  6모듈러 체: 5,216,954개 소수 찾음, 6.881997초 소요
  30모듈러 체: 5,216,954개 소수 찾음, 5.876001초 소요
  바이트배열 체: 5,216,954개 소수 찾음, 2.400088초 소요
  세그먼트 체: 5,216,954개 소수 찾음, 7.322342초 소요
  선형 체: 5,216,954개 소수 찾음, 9.089000초 소요
  극한 최적화 체: 5,216,954개 소수 찾음, 9.705499초 소요

크기 100,000,000에 대한 성능 측정 중...
  기본 체: 5,761,455개 소수 찾음, 11.902998초 소요
  최적화 체: 5,761,455개 소수 찾음, 6.211000초 소요
  비트 체: 5,761,455개 소수 찾음, 30.146074초 소요
  배열 체: 5,761,455개 소수 찾음, 9.205235초 소요
  6모듈러 체: 5,761,455개 소수 찾음, 7.351723초 소요
  30모듈러 체: 5,761,455개 소수 찾음, 6.310066초 소요
  바이트배열 체: 5,761,455개 소수 찾음, 2.584001초 소요
  세그먼트 체: 5,761,455개 소수 찾음, 8.151999초 소요
  선형 체: 5,761,455개 소수 찾음, 10.243011초 소요
  극한 최적화 체: 5,761,455개 소수 찾음, 10.805050초 소요
결과가 sieve_benchmark_results.csv에 저장되었습니다.

그래프를 생성하는 중...

소수 찾기, 알고리즘 성능 측정을 시작합니다...

크기 400,000,000에 대한 성능 측정 중...
  최적화 체: 21,336,326개 소수 찾음, 27.042099초 소요
  배열 체: 21,336,326개 소수 찾음, 37.221122초 소요
  6모듈러 체: 21,336,326개 소수 찾음, 33.125010초 소요
  30모듈러 체: 21,336,326개 소수 찾음, 28.655092초 소요
  바이트배열 체: 21,336,326개 소수 찾음, 11.125044초 소요
  세그먼트 체: 21,336,326개 소수 찾음, 31.529999초 소요
  선형 체: 21,336,326개 소수 찾음, 40.286133초 소요
  극한 최적화 체: 21,336,326개 소수 찾음, 42.410336초 소요

크기 600,000,000에 대한 성능 측정 중...
  최적화 체: 31,324,703개 소수 찾음, 40.856058초 소요
  배열 체: 31,324,703개 소수 찾음, 57.750140초 소요
  6모듈러 체: 31,324,703개 소수 찾음, 55.212205초 소요
  30모듈러 체: 31,324,703개 소수 찾음, 41.821157초 소요
  바이트배열 체: 31,324,703개 소수 찾음, 17.196048초 소요
  세그먼트 체: 31,324,703개 소수 찾음, 47.261804초 소요
  선형 체: 31,324,703개 소수 찾음, 60.990400초 소요
  극한 최적화 체: 31,324,703개 소수 찾음, 63.410334초 소요

크기 800,000,000에 대한 성능 측정 중...
  최적화 체: 41,146,179개 소수 찾음, 55.282412초 소요
  배열 체: 41,146,179개 소수 찾음, 75.594579초 소요
  6모듈러 체: 41,146,179개 소수 찾음, 69.476268초 소요
  30모듈러 체: 41,146,179개 소수 찾음, 57.084039초 소요
  바이트배열 체: 41,146,179개 소수 찾음, 22.622494초 소요
  세그먼트 체: 41,146,179개 소수 찾음, 62.489445초 소요
  선형 체: 41,146,179개 소수 찾음, 82.190220초 소요
  극한 최적화 체: 41,146,179개 소수 찾음, 84.392514초 소요

크기 1,000,000,000에 대한 성능 측정 중...
  최적화 체: 50,847,534개 소수 찾음, 68.751910초 소요
  배열 체: 50,847,534개 소수 찾음, 95.232901초 소요
  6모듈러 체: 50,847,534개 소수 찾음, 102.711907초 소요
  30모듈러 체: 50,847,534개 소수 찾음, 70.492689초 소요
  바이트배열 체: 50,847,534개 소수 찾음, 28.511875초 소요
  세그먼트 체: 50,847,534개 소수 찾음, 78.675977초 소요
  선형 체: 50,847,534개 소수 찾음, 104.387700초 소요
  극한 최적화 체: 50,847,534개 소수 찾음, 106.378612초 소요
결과가 sieve_benchmark_results.csv에 저장되었습니다.

그래프를 생성하는 중...