gpt4 book ai didi

c++ - 为什么在某些特定情况下拥有多个线程(并行处理)会降低性能?

转载 作者:行者123 更新时间:2023-11-30 01:34:28 26 4
gpt4 key购买 nike

我注意到为某些代码运行多个线程比运行一个线程要慢得多,而且我一直在绞尽脑汁想知道为什么,有人能帮忙吗?

代码解释:有时,我有一个非常大的数组,我需要以并行方式处理其中的一部分以进行优化,一行的每个“部分”都会在特定线程中循环并处理,现在我注意到,如果我只有一个“部分”,即整个数组和一个运行它的工作线程明显比我划分数组并将其作为具有不同线程的单独子数组处理要快得多。

    bool m_generate_row_worker(ull t_row_start,ull t_row_end)
{
for(;t_row_start<t_row_end;t_row_start++)
{
m_current_row[t_row_start]=m_singularity_checker(m_previous_row[t_row_start],m_shared_random_row[t_row_start]);

}
return true;
}

...
//code
...
for(unsigned short thread_indx=0;thread_indx<noThreads-1;thread_indx++)
{
m_threads_array[thread_indx]=std::thread(
m_generate_row_worker,this,
thread_indx*(m_parts_per_thread),(thread_indx+1)*(m_parts_per_thread));
}
m_threads_array[noThreads-1]=std::thread(m_generate_row_worker,this,
(noThreads-1)*(m_parts_per_thread),std::max((noThreads)*(m_parts_per_thread),m_blocks_per_row));
//join
for(unsigned short thread_indx=0;thread_indx<noThreads;thread_indx++)
{
m_threads_array[thread_indx].join();
}
//EDIT
inline ull m_singularity_checker(ull t_to_be_ckecked_with,ull
t_to_be_ckecked)
{
return (t_to_be_ckecked & (t_to_be_ckecked_with<<1)
& (t_to_be_ckecked_with>>1) ) | (t_to_be_ckecked_with &
t_to_be_ckecked);
}

最佳答案

why does having more than one thread(parallel processing) in some specific cases degrade performance?

  • 因为创建线程有开销。如果要执行的任务只有很小的计算成本,那么创建多个线程的成本就超过了并行节省的时间。当创建的线程明显多于 CPU 内核时尤其如此。
  • 因为很多算法不容易划分成独立的子任务。对其他线程的依赖需要同步,其开销在某些情况下可能超过并行节省的时间。
  • 因为在设计不佳的程序中,同步会导致所有任务按顺序处理,即使它们在单独的线程中也是如此。
  • 因为(取决于 CPU 架构)有时以其他方式正确执行,并且看似独立的任务具有有效的依赖性,因为它们在同一内存区域上运行。更具体地说,当一个线程写入一 block 内存时,在同一缓存行上操作的所有线程必须同步(CPU 自动为您完成)以保持一致。缓存未命中的成本通常远高于并行性节省的时间。这个问题被称为“虚假共享”。
  • 因为有时引入多线程会使程序变得更加复杂,这使得编译器/优化器更难利用指令级并行性。
  • ...

总而言之:线程并不是自动成倍提高程序性能的 Elixir 。


关于您的程序,根据您展示的摘录,我们不能排除上述任何潜在问题。

关于避免或发现上述问题的一些提示:

  • 不要创建比核心更多的线程,减少预期阻塞的线程数(等待输入、磁盘等)。
  • 仅使用多线程解决计算量大的问题(或在线程阻塞时工作,但这可能使用异步 I/O 和协程更有效地解决)。
  • 不要(或尽可能少地)从多个线程向单个设备(磁盘、NIC、虚拟终端等)执行 I/O,除非它是专门为处理它而设计的。<
  • 尽量减少线程之间的依赖关系。考虑所有可能导致同步的全局事物的访问,并避免它们。例如,避免内存分配。请记住,对标准容器的操作会进行内存分配。
  • 让不同线程接触的内存彼此远离(而不是数组的相邻小元素)。如果处理一个数组,将它分成连续的 block ,而不是每(线程数)个元素 strip 化一个元素。在某些极端情况下,额外复制到线程特定的数据结构,然后最后加入可能是有效的。
  • 如果您已尽力而为,但多线程的测量速度较慢,请考虑它是否不是解决您问题的好方法。

关于c++ - 为什么在某些特定情况下拥有多个线程(并行处理)会降低性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56330466/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com