使用 std 库的 c++ 多线程:比预期慢
c++ Multithreading with std library: slower than expected
我尝试使用标准库,特别是线程库。这个想法是用和没有多线程填充矩阵。我有 8 个内核。
void fillMatrix(int ID, std::vector<std::vector<double>> & lMatrix,int inThread){
for (int i = 0; i < 10000; ++i){
if (i % inThread == ID){
for (int j = 0; j < 10000; ++j){
lMatrix[i][j] = 123456.0;
}
}
}
}
void testMT(int inThread){
std::vector<std::thread> lPool;
std::vector<std::vector<double>> lMatrix(10000, std::vector<double>(10000));
for (int i = 0; i < inThread; ++i){
lPool.push_back(std::thread(std::bind(&fillMatrix,i, lMatrix,inThread)));
}
for (std::thread & t : lPool){
t.join();
}
}
主代码:
int main(){
const clock_t begin_time1 = clock();
testMT(1);
std::cout << float(clock() - begin_time1) / CLOCKS_PER_SEC;
}
testMT(1) 需要 2.1 秒运行, 而 testMT(8) 需要 7.032 秒。
知道吗?谢谢。
这会减慢速度,那么您将非常糟糕。
在 1 个线程的情况下,它总是为真,但在 8 个线程的情况下,它是真的,然后是假的假的......真。分支预测在此处失败。
最好将第一个 for 循环拆分/划分到每个线程。就像线程 1 执行矩阵的前 1/8 一样,线程 2 执行第二个 1/8,依此类推。
像这样:
for(int i = 10000*ID/inThread; i< 10000*(ID+1)/inThread; ++i)
在 ID=0 的情况下,循环将从 0 变为 2500,ID=1 将从 2500 变为 5000,依此类推。
您的代码无法按预期运行。线程运行后,您会注意到lMatrix
的所有元素都没有设置为 123456.0
。这是因为std::bind
将向量复制到自身中,然后将其发送到线程。您需要在绑定调用中使用std::ref(lMatrix)
才能正常工作并使用相同的矩阵。
改变
std::bind(&fillMatrix,i, lMatrix,inThread)
自
std::bind(&fillMatrix, i, std::ref(lMatrix), inThread)
因此,增加的执行时间的很大一部分可能是由拷贝开销引起的;每次线程启动 10000 x 10000 个分配和拷贝(然后是解除分配)。
您的线程都在修改附近内存位置中的同一对象。这意味着内存的所有权必须不断地从一个线程到另一个线程。
这不是线程的明智用法。如果您希望在众多线程同时操作同一对象时保持性能,则需要专业知识来处理错误共享之类的事情。
在某种程度上,这是一个非常重要的问题。
- 多线程代码
始终比单线程代码慢!(最好的情况是,您仍然需要支付启动和停止线程的费用)
并发使事情变得更快(有时)。
您的目标是让并发的收益超过使用线程的成本 - 并且好处如此显着,以至于它"支付"了代码增加的复杂性。 此示例未达到该目标。
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 带有 std::cout 的多线程控制台文本动画
- 将元素添加到 std::list 在多线程中,无需 C++ 互斥锁
- 在使用 std::cout 和多线程程序中如何避免数据竞争<iomanip>?
- 多线程中的 std::basicstring 的运行时分段错误C++点燃进程
- 如何使用 std::thread 逐行像素多线程?
- 在多线程环境中使用 std::call_once() 初始化
- 多线程计算均值和std并不能提高效率
- C++ std::endl 的多线程程序 I/O 问题
- std::d eque 和多线程访问
- 使用 std 库的 c++ 多线程:比预期慢
- 多线程程序导致分段错误,使用 std::list::p ush_back
- 在多线程环境中使用 std::string 时 Clang 的线程清理器警告
- scanf(), std::cin 在多线程环境中的行为如何
- QList、QVector或std::vector多线程使用
- 使用std::thread的C++多线程应用程序在Windows上运行良好,但在Ubuntu上则不然
- 可以用C++std::vector同时处理来自多线程的push_back
- 同步STD cout输出多线程
- std::vector::erase() (多线程) '断言 'px != 0' 失败。
- 使用多线程(std::async、std::thread或?)加速