多线程 - 比单线程慢

Posted

技术标签:

【中文标题】多线程 - 比单线程慢【英文标题】:multithreading - slower than single threading 【发布时间】:2017-10-15 20:57:50 【问题描述】:

当我使用多线程而不是单线程运行程序时,它会变慢,难道不应该更快吗?该程序应该从一个起始目录开始遍历所有目录并找到并打印所有名为 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);
        

有人能帮我找出在多线程运行时可能会减慢程序速度的原因吗?也许是一个解决方案?提前感谢您的所有帮助和建议!

【问题讨论】:

每个线程是否在单独的物理驱动器上工作? 不,它们都在同一个驱动器上,为什么? 嗯,来自多个线程的大量异步磁盘 I/O 请求可能会使试图最小化磁头移动的磁盘驱动程序系统不堪重负。这可能会导致对整体性能有害的身体头部抖动。当然,在搜索多个驱动器时,多线程可能很有用(特别是当它们的性能差异很大时,或者可能“失败”,例如当有网络驱动器时),在一个磁盘上尝试您建议的内容需要测试以查看是否有任何改进一切皆有可能,(很可能即使是两个线程也会对性能产生不利影响)。 谢谢你的回答,我想我明白了! 添加线程不是万能的。当然,引入 I/O 争用不太可能带来好处…… 【参考方案1】:

人们通常认为线程是培根的计算等价物(让一切变得更好)。

实际上:多线程并不总能加快速度。如果您的线程正在访问可以并行服务的不同硬件资源,多线程通常只会加快速度。在不共享内存(或很少共享内存)的两个不同内核上运行 CPU 密集型任务的两个线程可能会更快。如果他们共享内存或访问同一个磁盘,他们很有可能会竞争。

由于磁盘是迄今为止您的程序处理的最慢的资源,我一点也不惊讶您没有看到任何加速。尝试使用多个磁盘(每个磁盘一个线程)进行相同的实验,您可能会看到改进。

此外,您的程序具有的同步性(互斥锁)越多,您通常具有的并行性就越少。因此,性能将进一步受到影响。

【讨论】:

我想补充一点,如果你有多个线程并且你的代码是“完美的”(不是一次写入相同的内存,缓存友好并且没有互斥体)但你仍然有问题多个线程比单个线程慢,您应该寻找不是线程安全的库函数。 stdlib.h 中的 random() 函数就是一个例子。如果您在线程中使用它,您的程序在多个线程中将比在单个线程中慢。这种情况下的解决方案是寻找线程安全的等价物,例如 rand_r()

以上是关于多线程 - 比单线程慢的主要内容,如果未能解决你的问题,请参考以下文章

多线程比单线程慢

多线程函数性能比单线程差

C++11 多线程比单线程慢

多线程并发一定比单线程快吗?

python多线程不能利用多核cpu,但有时候多线程确实比单线程快。

java - 多线程中的简单计算比单线程中需要更长的时间