C 实现音节化算法,但速度非常慢

C 实现音节化算法,但速度非常慢,c,algorithm,performance,nlp,C,Algorithm,Performance,Nlp,我按照改进的Lansky算法实现了简单的音节化算法,但当我需要在超过200万单词的语料库上运行该算法时,它的速度非常慢。有人能告诉我是什么原因导致它这么慢吗?算法如下: 最后一个元音(元音组)之后的所有内容都属于最后一个音节 第一个元音(元音组)之前的所有内容都属于第一个音节 如果元音之间的辅音数为偶数(2n),则将其分为 一半第一部分属于左元音,第二部分属于右元音(n/n) 如果元音之间的辅音数量是奇数(2n+1),我们将它们分为 n/n+1个零件 如果元音之间只有一个辅音,则属于左元音 #包

我按照改进的Lansky算法实现了简单的音节化算法,但当我需要在超过200万单词的语料库上运行该算法时,它的速度非常慢。有人能告诉我是什么原因导致它这么慢吗?算法如下:

  • 最后一个元音(元音组)之后的所有内容都属于最后一个音节

  • 第一个元音(元音组)之前的所有内容都属于第一个音节

  • 如果元音之间的辅音数为偶数(2n),则将其分为 一半第一部分属于左元音,第二部分属于右元音(n/n)

  • 如果元音之间的辅音数量是奇数(2n+1),我们将它们分为 n/n+1个零件

  • 如果元音之间只有一个辅音,则属于左元音

    #包括
    #包括
    #定义元音“aeiou”
    int get_n_辅音_between(字符*单词,int长度){
    整数计数=0;
    int i=0;
    while(i++<长度){
    if(strchr(元音,*单词))中断;
    word++;
    计数++;
    } 
    返回计数;
    }
    无效音节化(字符*单词,int n_元音组){
    int i=0,length=strlen(单词),辅音;
    int音节=0,元音组=0,syl长度=0;
    字符*音节=单词;
    char hola[长度];
    memset(hola,0,长度);
    if(n_元音组<2){
    printf(“不能拆分为音节\n\n”);
    返回;
    }
    while(i
    `


  • 您可以做的事情很少:

    1) 对程序进行概要分析,并查看其大部分时间都在哪里

    2) 专注于代码中最重复的部分

    3) 避免多次扫描

    4) 不要进行不必要的操作。例如:

    (a)

    您是否需要始终
    memset
    hola

     memset(hola, 0, length);
    
    在我看来,你可以摆脱它

    (b)


    您可以从分析中获得非常好的提示,遵循这些提示并放大瓶颈

    您可以做的事情很少:

    1) 对程序进行概要分析,并查看其大部分时间都在哪里

    2) 专注于代码中最重复的部分

    3) 避免多次扫描

    4) 不要进行不必要的操作。例如:

    (a)

    您是否需要始终
    memset
    hola

     memset(hola, 0, length);
    
    在我看来,你可以摆脱它

    (b)


    您可以从分析中获得非常好的提示,遵循这些提示并放大瓶颈

    要检查实现是否正确,需要编写大量代码 正确,主要是因为我不知道术语(比如什么是 元音组)的算法。我查了一下,谷歌给了我很多信息 研究论文(我只能看到摘要)的教学大纲 不同的语言,所以我不确定代码是否正确

    但是我有一些建议可以让你的代码更快:

  • 将所有的
    strlen(word)
    循环条件中移出。节省时间
    在变量中,并使用该变量。所以从

    for (i = 0; i < strlen(word); i++)
    
    当您要检查字符是否为元音时:

    // 0x20 | c make c a lower case character
    if(vowel[0x20 | word[i]])
        syl_length++;
        i++;
        if (vowel_group) continue;
        vowel_group = 1;
    }
    
  • 第一个建议可能会使您的性能略有提高,编译器 非常聪明,可能会优化它。第二个建议可能会给出 你需要更多的性能,因为这只是一个查找。在最坏的情况下
    strchr
    必须多次遍历整个
    “aeiou”
    数组。1

    我还建议您分析代码。见和


    fotenotes

    1我制作了一个非常粗糙的程序,比较 建议。我加了一个fe
    for (i = 0; i < strlen(word); i++)
    
    size_t len = strlen(word);
    for(i = 0; i < len; i++)
    
    // as global variable
    char vowels[256];
    
    int main(void)
    {
        vowels['a'] = 1;
        vowels['e'] = 1;
        vowels['i'] = 1;
        vowels['o'] = 1;
        vowels['u'] = 1;
        ...
    }
    
    // 0x20 | c make c a lower case character
    if(vowel[0x20 | word[i]])
        syl_length++;
        i++;
        if (vowel_group) continue;
        vowel_group = 1;
    }
    
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    
    
    int test1(time_t t)
    {
        char text[] = "The lazy dog is very lazy";
        for(size_t i = 0; i < strlen(text); ++i)
            t += text[i];
    
        return t;
    }
    
    int test2(time_t t)
    {
        char text[] = "The lazy dog is very lazy";
        size_t len = strlen(text);
        for(size_t i = 0; i < len; ++i)
            t += text[i];
    
        return t;
    }
    
    #define VOWELS "aeiou"
    char vowels[256];
    
    int test3(time_t t)
    {
        char text[] = "The lazy dog is very lazy";
        size_t len = strlen(text);
        for(size_t i = 0; i < len; ++i)
        {
            if (strchr(VOWELS, text[i]))
                t += text[i];
            t += text[i];
        }
    
        return t;
    }
    
    int test4(time_t t)
    {
        char text[] = "The lazy dog is very lazy";
        size_t len = strlen(text);
        for(size_t i = 0; i < len; ++i)
        {
            if(vowels[0x20 | text[i]])
                t += text[i];
            t += text[i];
        }
    
        return t;
    }
    
    int main(void)
    {
        vowels['a'] = 1;
        vowels['e'] = 1;
        vowels['i'] = 1;
        vowels['o'] = 1;
        vowels['u'] = 1;
        long times = 50000000;
    
        long tmp = 0;
    
        clock_t t1 = 0, t2 = 0, t3 = 0, t4 = 0;
    
        for(long i = 0; i < times; ++i)
        {
            clock_t start,end;
            time_t t = time(NULL);
    
            start = clock();
            tmp += test1(t);
            end = clock();
    
            t1 += end - start;
            //t1 += ((double) (end - start)) / CLOCKS_PER_SEC;
    
            start = clock();
            tmp += test2(t);
            end = clock();
    
            t2 += end - start;
    
            start = clock();
            tmp += test3(t);
            end = clock();
    
            t3 += end - start;
    
            start = clock();
            tmp += test4(t);
            end = clock();
    
            t4 += end - start;
        }
    
        printf("t1: %lf %s\n", ((double) t1) / CLOCKS_PER_SEC, t1 < t2 ? "wins":"loses");
        printf("t2: %lf %s\n", ((double) t2) / CLOCKS_PER_SEC, t2 < t1 ? "wins":"loses");
        printf("t3: %lf %s\n", ((double) t3) / CLOCKS_PER_SEC, t3 < t4 ? "wins":"loses");
        printf("t4: %lf %s\n", ((double) t4) / CLOCKS_PER_SEC, t4 < t3 ? "wins":"loses");
        printf("tmp: %ld\n", tmp);
    
    
        return 0;
    }