多线程-比单线程慢

3

当我使用多线程而不是单线程运行我的程序时,速度变慢了,这难道不应该更快吗?这个程序应该从一个起始目录开始遍历所有目录,并查找并打印所有名为X的文件。以下是代码:

while(!done) {
        pthread_mutex_lock(&lock);
        if(!list_isEmpty(dirList)) {
            DIR *dir;
            struct dirent *d;
            char *folder;

            folder = strdup(list_inspect(1, dirList));
            list_remove(list_inspect(1,dirList), dirList);
            if(folder == NULL) {
                perror("failed strdup on path\n");
                pthread_mutex_unlock(&lock);
                continue;
            }
            pthread_mutex_unlock(&lock);
            dir = opendir(folder);
            if(dir == NULL) {
                perror(folder);
                free(folder);
                continue;
            }
            while ((d = readdir(dir)) != NULL) {
                if(strcmp(d->d_name, ".")==0 || strcmp(d->d_name, "..")==0) {
                    continue;
                }
                searchBasedOnType(folder, info, d);
            }
            closedir(dir);
            free(folder);
        }
        else {
            if(sleepCounter == info->nrthr-1) {
                done = true;
                pthread_cond_broadcast(&cond);
                pthread_mutex_unlock(&lock);
                break;
            }
            else {
                sleepCounter++;
                pthread_cond_wait(&cond, &lock);
                sleepCounter--;
                pthread_mutex_unlock(&lock);                
            }
        }   
    }

这里还有一个关于searchBasedOnTypes函数调用互斥锁等函数的示例:
char currentPath[FILENAME_MAX];
        struct stat buf;

        strcpy(currentPath,f);
        if(currentPath[strlen(currentPath)-1] != '/') {
            strcat(currentPath, "/");
        }
        strcat(currentPath, d->d_name);
        if(lstat(currentPath, &buf) == -1){
          perror(currentPath);
          return;
        }

        if(S_ISDIR(buf.st_mode)) {
            pthread_mutex_lock(&lock);
            char *newDir = malloc(sizeof(currentPath));
            if(newDir == NULL) {
                perror("Failed allocating memory for path\n");
                pthread_mutex_unlock(&lock);
                return;
            }
            strcpy(newDir, currentPath);
            printf("insert %s\n", newDir);
            list_insert(newDir, dirList);
            printf("done\n");
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&lock);
        }
        if(strcmp(name,d->d_name) == 0) {
            printf("%s\n",currentPath);
        }

有人能帮我找出在多线程运行时可能会减缓程序速度的原因以及解决方案吗?非常感谢您提前给予的所有帮助和建议!


每个线程都在单独的物理驱动器上工作吗? - Martin James
不,它们都在同一驱动器上,为什么? - Frans
3
许多来自多个线程的异步磁盘I/O请求可能会使试图最小化磁头移动的磁盘驱动系统不堪重负。这可能导致对整体性能有害的物理磁头抖动。当搜索多个驱动器时,多个线程肯定是有用的(特别是当它们在性能上差异很大或可能“失败”时,例如存在网络驱动器)。但在一个磁盘上尝试您建议的操作需要测试以查看是否可能有任何改进(甚至两个线程也可能对性能产生不利影响)。 - Martin James
谢谢您的回答,我想我明白了! - Frans
添加线程并非万能之策。当然,引入I/O争用不太可能带来好处... - underscore_d
1个回答

6
人们常常认为线程就是计算机中的培根(让所有事情都变得更好)。但实际上:多个线程并不总是会加快运行速度。只有当你的线程访问不同的硬件资源并可以并行服务时,多个线程通常才能加快速度。如果两个线程在两个不共享内存(或很少共享内存)的核心上运行CPU绑定任务,则可能会更快。但如果它们正在共享内存或同时访问同一磁盘,则很可能会有争用。
由于磁盘是程序处理中最慢的资源,因此我一点也不惊讶你没有看到任何加速。使用多个磁盘(每个磁盘一个线程)尝试相同的实验,你可能会看到更好的结果。
此外,程序的同步越多(互斥锁),你通常就会有越少的并行性。因此,性能会进一步受到影响。

我想补充一点,如果你有多个线程,而且你的代码“完美”(不会同时写入同一块内存,缓存友好且没有互斥锁),但仍然存在多个线程比单个线程慢的问题,那么你应该寻找那些不支持多线程的库函数。一个例子是stdlib.h中的random()函数。如果你在线程中使用它,你的程序将比单个线程更慢。在这种情况下的解决方案是寻找线程安全的替代函数,例如rand_r()。 - Werem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接