【发布时间】:2022-01-10 18:22:08
【问题描述】:
我创建了以下简单的测试程序来查看并行执行如何与 std::for_each 一起工作。
#include <iostream>
#include <vector>
#include <execution>
int main(int ac, char**av){
constexpr int size=5;
std::vector<int> v;
std::vector<int> expected;
for(int i=0; i<size; ++i) v.push_back(i);
expected.resize(size);
std::for_each(std::execution::par, v.begin(), v.end(), [&](auto x){ expected[x]=x; });
auto eq = std::equal(v.begin(), v.end(), expected.begin());
std::cout << "Compare: "<<eq<<"\n";
return 0;
}
该程序运行没有任何问题,但是如果我将它与经过清理的线程链接,我会收到数据竞争警告。这是程序输出:
Compare: 1
==================
WARNING: ThreadSanitizer: data race (pid=47090)
Write of size 8 at 0x7fab5399b200 by thread T8:
#0 memset /tp_src/gcc-9.2.0/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:762 (libtsan.so.10+0x35bc5)
#1 memset /tp_src/gcc-9.2.0/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:760 (libtsan.so.10+0x35bc5)
#2 rml::internal::BootStrapBlocks::allocate(rml::internal::MemoryPool*, unsigned long) ../../src/tbbmalloc/frontend.cpp:888 (libtbbmalloc.so.2+0x13700)
Previous write of size 8 at 0x7fab5399b200 by thread T10:
#0 memset /tp_src/gcc-9.2.0/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:762 (libtsan.so.10+0x35bc5)
#1 memset /tp_src/gcc-9.2.0/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:760 (libtsan.so.10+0x35bc5)
#2 rml::internal::BootStrapBlocks::allocate(rml::internal::MemoryPool*, unsigned long) ../../src/tbbmalloc/frontend.cpp:888 (libtbbmalloc.so.2+0x13700)
Thread T8 (tid=47099, running) created by thread T4 at:
#0 pthread_create /tp_src/gcc-9.2.0/libsanitizer/tsan/tsan_interceptors.cc:964 (libtsan.so.10+0x3057b)
#1 rml::internal::thread_monitor::launch(void* (*)(void*), void*, unsigned long) ../../src/tbb/../rml/server/thread_monitor.h:218 (libtbb.so.2+0x20ab8)
#2 tbb::internal::rml::private_worker::wake_or_launch() ../../src/tbb/private_server.cpp:297 (libtbb.so.2+0x20ab8)
#3 tbb::internal::rml::private_server::wake_some(int) ../../src/tbb/private_server.cpp:395 (libtbb.so.2+0x20ab8)
Thread T10 (tid=47101, running) created by thread T3 at:
#0 pthread_create /tp_src/gcc-9.2.0/libsanitizer/tsan/tsan_interceptors.cc:964 (libtsan.so.10+0x3057b)
#1 rml::internal::thread_monitor::launch(void* (*)(void*), void*, unsigned long) ../../src/tbb/../rml/server/thread_monitor.h:218 (libtbb.so.2+0x20ab8)
#2 tbb::internal::rml::private_worker::wake_or_launch() ../../src/tbb/private_server.cpp:297 (libtbb.so.2+0x20ab8)
#3 tbb::internal::rml::private_server::wake_some(int) ../../src/tbb/private_server.cpp:395 (libtbb.so.2+0x20ab8)
SUMMARY: ThreadSanitizer: data race ../../src/tbbmalloc/frontend.cpp:888 in rml::internal::BootStrapBlocks::allocate(rml::internal::MemoryPool*, unsigned long) [83/16871]
==================
看起来for_each已经完成,最后比较成功了。然而,一些后台线程使线程清理器在 main 完成期间不开心。
此示例是否有任何问题,或者这是线程清理程序中的错误或误报警告,我可以忽略它?
这是我的编译方式:
g++ -O3 -I$TBBINC -std=c++17 -fsanitize=thread ForEach.cpp $TBBLIB/libtbb.so -o ForEach
【问题讨论】:
-
我不认为你可以修改 UnaryFunction 中的其他元素,除了你给定的元素。
-
我不认为这是问题所在。此外,即使我将此 lambda 设为空,我仍然会收到相同的警告。
-
在这种情况下,将 lambda 的主体设置为空在您的 sn-p 中可能是有意义的。另外,如果 for_each 中的 lambda 没有通过引用捕获,你还会收到警告吗?
-
是的,如果 lambda 为空并且没有捕获任何内容,我仍然会收到警告。
-
我问了一个关于
for_each与周围代码同步的新问题:stackoverflow.com/questions/70278724/…
标签: c++ multithreading c++17 tbb