You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化大数模式筛选算法?目标提速10倍及支持1e15级运算

问题描述

我需要开发一个算法筛选含特定模式的大数(例如101010101010101这类数字)。目前处理1亿条数据耗时4-5秒,其中约9950万条会被过滤。我的目标是能处理1e15级别的数据,同时把1亿数据的处理耗时降到0.4秒以内。我已经尝试了多线程优化、将int替换为unsigned long long等手段,让代码提速了约10倍,但还需要至少再提速10倍。也可以更换开发语言,希望得到帮助。

当前代码
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <windows.h>

#define NUM_THREADS 8
#define MAX_NUM 100000ULL  

typedef struct {
    unsigned long long int start;
    unsigned long long int end;
    unsigned long long int count;
} ThreadData;

// 检查是否存在连续递增或递减的数位
bool has_consecutive_digits(const char* password, int length) {
    int len = strlen(password);
    for (int i = 0; i <= len - length; i++) {
        bool increasing = true, decreasing = true;
        for (int j = 0; j < length; j++) {
            if (password[i+j] != password[i] + j) increasing = false;
            if (password[i+j] != password[i] - j) decreasing = false;
        }
        if (increasing || decreasing) return true;
    }
    return false;
}

// 检查是否存在重复次数过多的数位
bool has_repeated_digits(const char* password, int max_repeats) {
    int counts[10] = {0};
    int len = strlen(password);
    for (int i = 0; i < len; i++) {
        counts[password[i] - '0']++;
        if (counts[password[i] - '0'] > max_repeats) return true;
    }
    return false;
}

// 检查是否存在回文模式
bool has_palindromic_pattern(const char* password, int length) {
    int len = strlen(password);
    for (int i = 0; i <= len - length; i++) {
        bool is_palindrome = true;
        for (int j = 0; j < length / 2; j++) {
            if (password[i+j] != password[i+length-1-j]) {
                is_palindrome = false;
                break;
            }
        }
        if (is_palindrome) return true;
    }
    return false;
}

// 检查是否包含常见模式子串
bool is_substring_of_common_patterns(const char* password) {
    const char* common_patterns[] = {
        "123456", "654321", "111111", "222222", "333333",
        "012345", "543210", "987654", "000000", "999999"
    };
    for (int i = 0; i < 10; i++) {
        if (strstr(password, common_patterns[i])) return true;
    }
    return false;
}

// 检查是否存在交替数位模式
bool has_alternating_digits(const char* password, int length) {
    int len = strlen(password);
    for (int i = 0; i <= len - length; i++) {
        bool valid = true;
        for (int j = 0; j < length; j++) {
            if ((j % 2 == 0 && password[i+j] != password[i]) ||
                (j % 2 == 1 && password[i+j] == password[i])) {
                valid = false;
                break;
            }
        }
        if (valid) return true;
    }
    return false;
}

// 检查是否存在连续的递增/递减块
bool has_increasing_or_decreasing_blocks(const char* password, int block_size) {
    int len = strlen(password);
    for (int i = 0; i <= len - block_size; i += block_size) {
        if (has_consecutive_digits(password + i, block_size)) return true;
    }
    return false;
}

// 检查是否存在镜像块
bool has_mirrored_blocks(const char* password, int block_size) {
    int len = strlen(password);
    for (int i = 0; i <= len - 2 * block_size; i += block_size) {
        bool mirrored = true;
        for (int j = 0; j < block_size; j++) {
            if (password[i + j] != password[i + block_size * 2 - 1 - j]) {
                mirrored = false;
                break;
            }
        }
        if (mirrored) return true;
    }
    return false;
}

// 检查数字是否包含过简单的模式
bool is_pattern_too_simple(const char* password) {
    return has_consecutive_digits(password, 3) ||
           has_repeated_digits(password, 1) ||
           has_palindromic_pattern(password, 4) ||
           is_substring_of_common_patterns(password) ||
           has_alternating_digits(password, 4) ||
           has_increasing_or_decreasing_blocks(password, 2) ||
           has_mirrored_blocks(password, 4);
}

// 验证数字是否合法(不包含简单模式)
bool is_valid_password(const char* password) {
    return !is_pattern_too_simple(password);
}

DWORD WINAPI check_passwords(LPVOID arg) {
    ThreadData* data = (ThreadData*)arg;
    char password[7];  // 存储6位数字+结束符
    data->count = 0;

    for (unsigned long long int i = data->start; i < data->end; i++) {
        sprintf(password, "%06llu", i);  // 生成6位数字字符串
        if (is_valid_password(password)) {
            data->count++;
        }
    }

    return 0;
}

int main() {
    HANDLE threads[NUM_THREADS];
    ThreadData thread_data[NUM_THREADS];
    unsigned long long int range = MAX_NUM / NUM_THREADS;
    unsigned long long total_count = 0;

    // 创建线程
    for (int i = 0; i < NUM_THREADS; i++) {
        thread_data[i].start = i * range;
        thread_data[i].end = (i + 1) * range;
        threads[i] = CreateThread(NULL, 0, check_passwords, &thread_data[i], 0, NULL);
        if (threads[i] == NULL) {
            fprintf(stderr, "Error creating thread %d\n", i);
            return 1;
        }
    }

    // 等待线程完成并汇总结果
    for (int i = 0; i < NUM_THREADS; i++) {
        WaitForSingleObject(threads[i], INFINITE);
        DWORD exit_code;
        if (GetExitCodeThread(threads[i], &exit_code)) {
            total_count += thread_data[i].count;
        } else {
            fprintf(stderr, "Error getting thread exit code %d\n", i);
        }
        CloseHandle(threads[i]);
    }

    // 输出合法数字总数
    printf("Anzahl der gültigen Zahlen: %llu\n", total_count);

    return 0;
}
优化建议
  • 彻底移除字符串转换:当前最大性能瓶颈是sprintf的字符串转换及后续字符串操作。直接通过取模、除法运算提取数字的每一位,完全避免字符串的内存分配与操作开销,这能至少节省50%以上的耗时。
  • 调整检查顺序:在is_pattern_too_simple中,把触发概率最高的检查(比如has_repeated_digits,毕竟99.5%的数据会被过滤)放在最前面,利用逻辑或的短路特性,提前终止不必要的后续检查。
  • 用数学运算替代字符串匹配:把常见模式(如123456、111111)转换成数字,直接通过数学方法判断数字是否包含这些连续数位。比如检查三位连续数位时,直接提取三位数字判断是否满足递增/递减关系,而非调用字符串处理函数。
  • SIMD指令集优化:利用x86平台的SSE/AVX指令集,批量处理多个数字的数位检查,同时对多组数字进行模式判断,大幅提升并行处理效率。
  • 从过滤转向生成合法数:由于合法数字占比仅0.5%,直接通过组合数学生成所有符合要求的数字,而非遍历所有数再过滤。这种方式处理1e15级数据时,无需遍历海量无效数据,效率会指数级提升。
  • 开启编译器最高优化:编译时添加-O3选项,让编译器进行循环展开、函数内联、死代码消除等深度优化,能带来显著的性能提升。
  • 更换语言的选择:如果继续使用编译型语言,C++的模板元编程和高效标准库可以进一步优化;Rust的零成本抽象和安全并发模型,性能接近C且能简化并行逻辑的开发。

内容的提问来源于stack exchange,提问作者Simon Rogl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 04:57:33