我需要解析一个巨大的文档,其中一个查询要求我在文档的某些字符串中计算单词。这些字符串通常在2000到30000字之间,而我的程序只需要12秒就能解析所有的字符串。花费时间最长的查询并不奇怪,它需要一个单词计数。
我试着用管道和叉子来加速这个过程。
的工作方式:
我把绳子除以二。如果我碰巧把一个单词分成两个-- if text[i] != ' ' etc --那么被分割的文本的左边一直往左看,直到它遇到一个空格,直到它到达那个空格为止。右侧将这半个单词计算为一个完整的单词,并一直计算到字符串的末尾。如果我在空格之间划分,循环就不会发生,程序将继续到下一步。编辑:可以是空格,也可以是\n或\t
在那之后,我做叉子,通过管道在叉子之间交流。通过管道的是文本的一半的单词计数。然后将它添加到另一半的单词计数中,然后返回总数。
问题:
在一个测试代码示例中,它似乎毫无帮助。执行的时间似乎仍然是一样的,就好像我一蹴而就。
大问题
此函数将在整个解析过程中运行大约60000次。我的程序执行时间太长了,事实上我在2分钟后不得不取消它.
我在哪里需要帮助?
我需要帮助确切地知道为什么我的功能是:
( a)与单核实现相比,这种所谓的双核实现甚至没有稍微快一点。
( 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;
}发布于 2017-04-21 18:54:59
为了跟进我以上的评论:
如果I/O是您的瓶颈:
考虑将文件名传递到单词计数程序中,然后使用简单的fread()和fwrite()调用来管理磁盘I/O,这些调用同时读取整个文件。从它的声音,您的文件应该在内存中合理的只有300千字-也许最坏的情况下3 3Meg文件?很快就会进入记忆。
然后,用你的话计算数据上的魔力。我的猜测是,您甚至不需要担心线程之类的问题,因为在内存中进行扫描对于您的任务来说几乎是即时的。见鬼,我敢打赌,即使使用strtok()来寻找空格和标点符号也足够好。
但是,如果我错了,好消息是,这些数据可以很容易地分成多个部分,并传递给各个线程来计数数据,然后在完成后收集和添加。
如果I/O不是,那么上面的练习将毫无收获,但至少可以很快地作为测试用例进行编码。
https://stackoverflow.com/questions/43530814
复制相似问题