gpt4 book ai didi

multithreading - (优化?)关于 GCC std::thread 的错误

转载 作者:行者123 更新时间:2023-12-03 22:45:09 25 4
gpt4 key购买 nike

在使用 std::thread 测试某些功能时, 一位 friend 遇到了 GCC 的问题,我们认为值得询问这是 GCC 错误还是这段代码有问题(代码打印(例如)“7 8 9 10 1 2 3”,但我们希望每个要打印的 [1,10] 中的整数):

#include <algorithm>
#include <iostream>
#include <iterator>
#include <thread>

int main() {
int arr[10];
std::iota(std::begin(arr), std::end(arr), 1);
using itr_t = decltype(std::begin(arr));

// the function that will display each element
auto f = [] (itr_t first, itr_t last) {
while (first != last) std::cout<<*(first++)<<' ';};

// we have 3 threads so we need to figure out the ranges for each thread to show
int increment = std::distance(std::begin(arr), std::end(arr)) / 3;
auto first = std::begin(arr);
auto to = first + increment;
auto last = std::end(arr);
std::thread threads[3] = {
std::thread{f, first, to},
std::thread{f, (first = to), (to += increment)},
std::thread{f, (first = to), last} // go to last here to account for odd array sizes
};
for (auto&& t : threads) t.join();
}

以下替代代码有效:
int main()
{
std::array<int, 10> a;
std::iota(a.begin(), a.end(), 1);
using iter_t = std::array<int, 10>::iterator;
auto dist = std::distance( a.begin(), a.end() )/3;
auto first = a.begin(), to = first + dist, last = a.end();
std::function<void(iter_t, iter_t)> f =
[]( iter_t first, iter_t last ) {
while ( first != last ) { std::cout << *(first++) << ' '; }
};
std::thread threads[] {
std::thread { f, first, to },
std::thread { f, to, to + dist },
std::thread { f, to + dist, last }
};
std::for_each(
std::begin(threads),std::end(threads),
std::mem_fn(&std::thread::join));
return 0;
}

我们认为这可能与对函数的数量的无序评估有关,或者只是这样 std::thread复制非 std::ref 时应该可以工作- 限定参数。然后我们用 Clang 测试了第一个代码并且它可以工作(因此开始怀疑 GCC 错误)。

使用的编译器:GCC 4.7、Clang 3.2.1

编辑: GCC 代码的第一个版本给出了错误的输出,但第二个版本给出了正确的输出。

最佳答案

从这个修改后的程序:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <thread>
#include <sstream>

int main()
{
int arr[10];
std::iota(std::begin(arr), std::end(arr), 1);
using itr_t = decltype(std::begin(arr));

// the function that will display each element
auto f = [] (itr_t first, itr_t last) {
std::stringstream ss;
ss << "**Pointer:" << first << " | " << last << std::endl;
std::cout << ss.str();
while (first != last) std::cout<<*(first++)<<' ';};

// we have 3 threads so we need to figure out the ranges for each thread to show
int increment = std::distance(std::begin(arr), std::end(arr)) / 3;
auto first = std::begin(arr);
auto to = first + increment;
auto last = std::end(arr);
std::thread threads[3] = {
std::thread{f, first, to},
#ifndef FIX
std::thread{f, (first = to), (to += increment)},
std::thread{f, (first = to), last} // go to last here to account for odd array sizes
#else
std::thread{f, to, to+increment},
std::thread{f, to+increment, last} // go to last here to account for odd array sizes
#endif
};
for (auto&& t : threads) {
t.join();
}
}

我添加了 first 的打印件和 last lambda 函数的指针 f ,并找到这个有趣的结果(当 FIX 未定义时):
**Pointer:0x28abd8 | 0x28abe4
1 2 3 **Pointer:0x28abf0 | 0x28abf0
**Pointer:0x28abf0 | 0x28ac00
7 8 9 10

然后我为 #ELSE 添加一些代码 #ifndef FIX 的案例.它运作良好。

- 更新:这个结论,下面的原帖,是错误的。我的错。请参阅下面乔希的评论 -

I believe the 2nd line std::thread{f, (first = to), (to +=
increment)},
of threads[] contains a bug: The assignment inside the two pairs of parenthesis, can be evaluated in any order, by the parser. Yet the assignment order of 1st, 2nd and 3rd argument of the constructor needs to keep the order as given.



--- 更新:更正---

因此上面的调试打印结果表明 GCC4.8.2(我的版本)
仍然有问题(不是说 GCC4.7),但 GCC 4.9.2 修复了这个错误,因为
由 Maxim Yegorushkin 报道(见上面的评论)。

关于multithreading - (优化?)关于 GCC std::thread 的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25115189/

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