有没有办法我只能使用8个mutices并具有相同的功能?
在这里大声思考……并不确定这会有多高效,但是:您可以创建锁定某些索引的方法:
vector<int> mutexed_slots; std::mutex mtx; bool lock_element(int index) { std::lock_guard<std::mutex> lock(mtx); // Check if item is in the mutexed list if ( !std::find(mutexed_slots.begin(), mutexed_slots.end(), index) != vector.end() ) { // If its not then add it - now that array value is safe from other threads mutexed_slots.emplace_back(index); return true; } return false; } void unlock_element(int index) { std::lock_guard<std::mutex> lock(mtx); // No need to check because you will only unlock the element that you accessed (unless you are a very naughty boy indeed) vec.erase(vec.begin() + index); }
注意:这是一个想法的开始,所以不要太难敲它!它也是未经测试的伪代码.它并不是真正的最终答案 – 而是作为一个起点.请添加评论以改进或建议这是/似乎不合理.
更多要点:
>可能有更高效的STL使用
>您可以将所有这些与数据一起包含在一个类中
>你需要循环遍历lock_element()直到它返回true – 此刻再次不是很漂亮.这种机制可以改进.
>每个线程都需要记住它们当前正在处理哪个索引,以便它们只解锁该特定的索引 – 再次将其集成到一个类中以确保该行为.
但作为一个概念 – 可行吗?我想如果你需要真正的快速访问(也许你这么做)这可能不是那么有效,想法?
更新
如果每个线程/工作者在mutexed_slots中“注册”其自己的条目,则可以使这更有效.然后,向量中不会有push_back / remove(除了在开始/结束时).所以每个线程只设置它已锁定的索引 – 如果它没有锁定,那么它只是设置为-1(或类似).我认为还有更多这样的效率改进.同样,为您完成所有这一切的完整课程将是实现它的方法.
测试/结果
我为此实现了一个测试器,因为我非常喜欢这种东西.我的实现是here
我认为它是一个公共github回购 – 所以欢迎你看看.但是我将结果发布在顶级自述文件上(所以滚动一点看看它们).我实施了一些改进,以便:
>在运行时没有插入/删除保护阵列
>没有必要使用lock_guard进行“解锁”,因为我不依赖于std :: atomic索引.
以下是我的摘要打印输出:
摘要:
当工作负载为1ms(执行每个操作所花费的时间)时,完成的工作量为:
> 9808受保护
> 8117正常
注意这些值变化,有时正常值较高,没有明显的赢家.
当工作负载为0ms(基本上增加几个计数器)时,完成的工作量为:
> 9791264受保护
> 29307829为正常
所以在这里你可以看到使用互斥保护减慢了工作速度约三分之一(1/3).这个比例在测试之间是一致的.
我也对1名工人进行了相同的测试,并且相同的比率大致相同.然而,当我使阵列变小(~1000个元素)时,完成的工作量在工作负载为1ms时仍大致相同.但是当工作量非常轻时,我得到的结果如下:
> 5621311
> 39157931
这大约慢了7倍.
结论
>阵列越大,碰撞越少 – 性能越好.
>工作负荷越长(每个项目),使用保护机制的差异就越小.
似乎锁定通常只增加一个比增加几个计数器慢2-3倍的开销.这可能是由实际碰撞造成的,因为(从结果中)记录的最长锁定时间是一个巨大的40ms – 但这是因为工作时间非常快,因此发生了许多碰撞(每次碰撞成功锁定约8次).