gpt4 book ai didi

C++ 多组可变函数参数

转载 作者:行者123 更新时间:2023-11-30 01:06:37 24 4
gpt4 key购买 nike

我正在尝试优化计算密集型应用程序中一个非常低级别且广泛使用的函数。假设我有以下类型:

template<typename T, int N> 
class Elem {...};

我想编写一个可以调用的函数,例如:

template<typename T, int N>
void func(const Elem<T, N> & ... /*N elements*/, Elem<T, N> & ... /* N elements*/)

我正在寻找一种方法,我可以确定编译器将能够删除函数签名引入的任何临时变量。

元素通常是从 vector/数组的不同位置获取的元素。例如。 :

Elem<float, 3> inputs[10];
Elem<float, 3> outputs[10];
...
func(input[4], input[2], input[9], output[6], output[8], output[1]);

答案可能是初始化列表,但我担心它可能会有一些开销......

注意:上面的间接索引都是编译时计算函数,并且范围很短。


编辑

事实上,我想要的是:

template<typename... T, int N>
void func(const Elem<T, N>&... inputs, const Elem<T, N>&... outputs)
{
static_assert(sizeof...(inputs) == N, "invalid number of arguments");
static_assert(sizeof...(outputs) == N, "invalid number of arguments");
static_assert(std::is_same<std::integral_constant<int N>...>::value, "invalid arguments");
}

但是我不能让这段代码在 VS2017 上编译。答案可以是 C++17。

最佳答案

我会将每个集合作为一个引用元组传递,您可以使用 std::tie 进行创建。

在大多数情况下,根本不会有任何开销,因为编译器会查看所有元组构造。

例子:

#include <tuple>
#include <type_traits>


template<class T, std::size_t N>
struct Elem {
T value() const { return val; }

T val;
};

Elem<float, 3> input[10];
Elem<float, 3> output[10];


namespace detail {
template<typename T, typename F, std::size_t... Is>
constexpr auto tuple_foreach(T&& tup, F& f, std::index_sequence<Is...>) {
using expand = int[];
void(expand{0,
(f(std::get<Is>(std::forward<T>(tup))), 0)...
})
;
}
}

template<typename T, typename F, std::size_t TupSize = std::tuple_size_v<std::decay_t<T>>>
constexpr auto tuple_foreach(T&& tup, F f) {
return detail::tuple_foreach(
std::forward<T>(tup), f,
std::make_index_sequence<TupSize>{}
);
}

template<class Set1, class Set2>
auto func(Set1 set1, Set2 set2)
{
constexpr auto N1 = std::tuple_size<Set1>::value;
constexpr auto N2 = std::tuple_size<Set2>::value;
static_assert(N1 == N2, "");

// now do things with std::get<0 ... N-1>(set1) and
// std::get<0 ... N-1>(set2);

using result_type = std::decay_t<decltype(std::get<0>(set1).value())>;

// let's compute the sum of the inputs
result_type result = 0;
tuple_foreach(set1,
[&](auto&& elem)
{
result += elem.value();
});
tuple_foreach(set2,
[&](auto&& elem)
{
result += elem.value();
});

return result;
}

void emit(float);

int main()
{
auto x = func(std::tie(input[4], input[2], input[9]),
std::tie(output[6], output[8], output[1]));
emit(x);
}

使用编译器设置 -O2 发出的程序集:

main:
pxor xmm0, xmm0
sub rsp, 8
addss xmm0, DWORD PTR input[rip+16]
addss xmm0, DWORD PTR input[rip+8]
addss xmm0, DWORD PTR input[rip+36]
addss xmm0, DWORD PTR output[rip+24]
addss xmm0, DWORD PTR output[rip+32]
addss xmm0, DWORD PTR output[rip+4]
call emit(float)
xor eax, eax
add rsp, 8
ret

没有比这更高效的了。

关于C++ 多组可变函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46176713/

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