gpt4 book ai didi

c++ - 如何避免相似模板中的代码重复

转载 作者:行者123 更新时间:2023-11-30 01:48:23 25 4
gpt4 key购买 nike

我实现了一个 parallel_accumulate,类似于 std::acumulate 但使用线程来并行化累积工作。有两个版本的 std::accumulate,第二个采用附加运算符进行累加,而第一个隐式假定加法。第一个版本:

template<typename Iterator, typename T>
static T parallel_accumulate(Iterator first, Iterator last, T init)
{
unsigned long const length = std::distance(first, last);
if (!length) return init;

unsigned long const max_ths = 64;
unsigned long const hw_ths = std::thread::hardware_concurrency();
unsigned long const num_ths = std::min(hw_ths != 0 ? hw_ths : 2, max_ths);
unsigned long const block_size = length / num_ths;
std::vector<T> results(num_threads);
std::vector<std::thread> threads(num_ths);
Iterator block_start = first;

for (unsigned long i = 0; i < num_ths; ++i) {
Iterator block_end = block_start;
std::advance(block_end, block_size);
threads[i] = std::thread( // diff1
_noop<Iterator,T>(),
block_start,
block_end,
std::ref(results[i]));
block_start = block_end;
}
std::for_each(threads.begin(), threads.end(),std::mem_fn(&std::thread::join));

return std::accumulate(results.begin(), results.end(), init); // diff2
}

第二个版本:

template<typename Iterator, typename T, typename BinOp>
static T parallel_accumulate(Iterator first, Iterator last, T init, BinOp op)
{
unsigned long const length = std::distance(first, last);
if (!length) return init;

unsigned long const max_ths = 64;
unsigned long const hw_ths = std::thread::hardware_concurrency();
unsigned long const num_ths = std::min(hw_ths != 0 ? hw_ths : 2, max_ths);
unsigned long const block_size = length / num_ths;
std::vector<T> results(num_threads);
std::vector<std::thread> threads(num_ths);
Iterator block_start = first;

for (unsigned long i = 0; i < num_ths; ++i) {
Iterator block_end = block_start;
std::advance(block_end, block_size);
threads[i] = std::thread( // diff1
_op<Iterator,T,BinOp>(),
block_start,
block_end,
std::ref(results[i]));
block_start = block_end;
}
std::for_each(threads.begin(), threads.end(),std::mem_fn(&std::thread::join));

return std::accumulate(results.begin(), results.end(), init, op); // diff2
}

正如您可以很容易地看到我的两个版本的实现仅在两行不同,我如何避免在 C++ 中优雅地复制此代码(即不使用#defines)?

(请注意,为清楚起见,我省略了 _noop 和 _op,它们只是调用相应版本的 std::accumulate 的可调用结构)

更新:我想要没有显式加法运算符的第一个版本(因为隐式 std::accumulate 更快)。

最佳答案

如果你有 C++14 透明运算符仿函数,那么第一个版本可以实现为

template<typename Iterator, typename T>
static T parallel_accumulate(Iterator first, Iterator last, T init)
{
return parallel_accumulate(first, last, init, std::plus<>());
}

如果你不这样做,相当于std::plus<>简直就是

struct my_plus {
template<class T, class U>
auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) + std::forward<U>(u)) {
return std::forward<T>(t) + std::forward<U>(u);
}
};

关于c++ - 如何避免相似模板中的代码重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30501838/

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