2017-04-20 38 views
0

我需要解析一个巨大的文档和查询的一个要求我算在文档的特定字符串的话。这些字符串通常有2000到30000个字,我的程序只需要12秒钟就可以解析所有的字。查询需要最长的时间,这并不令人惊讶,这是需要计算字数的查询。双核字计数器缓慢

我尝试使用管道和叉子,试图加速这一进程。

工作原理:

我拿串和除以二。如果我碰巧在两分一个字 - if text[i] != ' ' etc - 然后划分文本的左侧一直寻找到左边,直到它遇到一个空间,直到它到达的空间只计算的话。右侧将这个半字计为一个完整的单词并继续计数直到到达字符串的末尾。如果我在两个空间之间划分,则循环不会发生,程序将继续执行下一步。 编辑:可能是空间或\n\t

之后,我做了一个叉子,并通过管道之间的叉子之间进行通信。通过管道的是文本的一半的字数。然后它被添加到另一半的字数并返回总数。

问题:

在测试代码示例,它似乎并没有帮助的。执行时间似乎仍然是一样的,就好像我一口气做完了一样。

的一个大问题

该功能意味着整个解析被附近跑60000倍。而我的节目时间太长执行,其实我有2分钟后取消它......

哪里需要帮助吗?

我需要确切知道为什么我的帮助功能:

一)甚至比单核,有了它,所谓的双核实现稍快得到。

B)这么长时间在实际的程序


我希望这不是C和叉子一个问题/管都只是我想要的东西太慢了,我希望我只是不知道某事。

-

下面的代码!

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

long count(char* xStr) { 
    long num = 0; 

    // state: 
    const char* iterar = (const char*) xStr; 
    int in_palavra = 0; 

    do switch(*iterar) { 
     case '\0': 
     case ' ': case '\t': case '\n': 
      if (in_palavra) { in_palavra = 0; num++; } 
      break; 
     default: in_palavra = 1; 
    } while(*iterar++); 

    return num; 
} 


long wordCounter(char* text) { 
    int LHalf = strlen(text)/2; 
    int DHalf = LHalf; 
    while(text[LHalf] != ' ' && text[LHalf] != '\n' && text[LHalf] != '\t') { 
     if(LHalf > 0){ 
      LHalf--; 
     } 
     else break; 
    } 
    char* lft = malloc(LHalf); 
    char* rgt = malloc(DHalf); 

    strncpy(lft, text, LHalf); 
    strncpy(rgt, text + DHalf, DHalf); 

    int fd[2]; 
    pid_t childpid; 
    pipe(fd); 

    long size_left; 
    long size_right; 
    if((childpid = fork()) == -1) { 
     perror("Error in fork"); 
    } 

    if(childpid == 0) { 
     close(fd[0]); 

     size_left = count(lft); 
     int w = write(fd[1], &size_left, sizeof(long)); 
     close(fd[1]); //desnecessario 
     exit(0); 
    } 

    else { 
     close(fd[1]); 

     int r = read(fd[0], &size_left, sizeof(long)); 
     size_right = count(rgt); 
     close(fd[0]); 
     wait(0); 
    } 

    long total = size_right + size_left; 


    free(lft); 
    free(rgt); 
    return total; 
} 

int main(int argc, char const *argv[]) { 
    long num = wordCounter("aaa aaa aa a a a a a a sa sa as sas sa sa saa sa sas aa sa sas sa sa"); //23 words 
    printf("%ld\n", num); 
    return 0; 
} 
+0

那么,有所有mallocing和复制:(每个线程/进程只需要一个开始地址和长度,当然?为什么malloc/copy? – ThingyWotsit

+0

另外,请注意,发信号等待的线程/进程约10-20倍快 – ThingyWotsit

+0

@ThingyWotsit你是什么意思?我只是开始乱用多线程,所以我不知道太多:) –

回答

0

要跟进我的上述评论:

如果I/O是您的瓶颈:

考虑通过文件名到您的单词统计程序,然后管理磁盘I/O自己用简单的fread()fwrite()调用一次读取整个文件。从它的声音来看,你的文件只能在30万字以内合理地存储到内存中 - 也许是最差的3Meg文件?这应该很快读入内存。

然后,对数据进行计数魔术。我的猜测是,你甚至不需要担心线程或类似的问题,因为通过内存扫描应该几乎是你的任务的即时。哎呀,我敢打赌,即使使用strtok()寻找空格和标点符号也可能足够好。

但是,如果我错了,好消息是这个数据可以很容易地分成多个部分,并传递给个人pthreads来统计数据,然后收集和添加完成后。

如果I/O不是,那么上述练习根本不会显示任何增益,但至少它可以作为测试用例很快编码。