gpt4 book ai didi

c++ - 如何在两个 boost::multi_arrays (C++) 之间执行数学运算?

转载 作者:行者123 更新时间:2023-12-02 10:13:17 25 4
gpt4 key购买 nike

如何在两个 boost::multi_arrays 之间执行数学运算?
将两个值类型为 double 的数组相加的示例:

auto array1 = boost::multi_array<double, 2>(boost::extents[10][10]);
auto array2 = boost::multi_array<double, 2>(boost::extents[10][10]);

auto array3 = array1 + array2; //Does not compile
我知道的一种可能性是英特尔 IPP 库。可以使用例如添加两个矩阵来完成 ippiAdd_ .但遗憾的是,英特尔 IPP 不支持双值相加。
那么有人知道除了英特尔 IPP 之外的另一个库分别是克服英特尔 IPP 中受限值类型缺点的解决方案吗?

最佳答案

你可以“随便写”:

namespace ArrayOperators {
template <typename L, typename R>
static inline auto operator+(L const& l, R const& r) {
return ArrayOp {std::plus<>{}} (l, r); }

template <typename L, typename R>
static inline auto operator-(L const& l, R const& r) {
return ArrayOp {std::minus<>{}} (l, r); }

template <typename L, typename R>
static inline auto operator/(L const& l, R const& r) {
return ArrayOp {std::divides<>{}} (l, r); }

template <typename L, typename R>
static inline auto operator*(L const& l, R const& r) {
return ArrayOp {std::multiplies<>{}} (l, r); }
}
当然,这需要我们实际实现 ArrayOp可调用。我冒昧地
  • 为异构数组实现它(所以当左手和右手有不同的元素类型时)
  • 在右侧不是数组的情况下实现它,在这种情况下,标量操作数将应用于左侧
  • 的每个元素
  • 我没有支持
  • 就地操作
  • 数组引用/数组(常量) View
  • 不同形状或维度的数组


  • 开始:
    template <typename Op> struct ArrayOp {
    Op op;
    explicit ArrayOp(Op op) : op(op) {}

    template <typename T, typename Scalar, size_t Dim> auto operator()(
    boost::multi_array<T, Dim> const& l,
    Scalar const& v) const
    {
    std::array<int, Dim> shape;
    std::copy_n(l.shape(), Dim, shape.data());

    using R = boost::multi_array<decltype(op(T{}, v)), Dim>;
    R result(shape);

    std::transform(
    l.data(), l.data()+l.num_elements(),
    result.data(),
    [&op=op,v](auto const& el) { return op(el, v); });

    return result;
    }

    template <typename T, typename U, size_t Dim> auto operator()(
    boost::multi_array<T, Dim> const& l,
    boost::multi_array<U, Dim> const& r) const
    {
    std::array<int, Dim> shape;
    std::copy_n(l.shape(), Dim, shape.data());
    assert(std::equal(shape.begin(), shape.end(), r.shape()));

    using R = boost::multi_array<decltype(op(T{}, U{})), Dim>;
    R result(shape);

    std::transform(
    l.data(), l.data()+l.num_elements(),
    r.data(), result.data(),
    [&op=op](auto const& v1, auto const& v2) { return op(v1, v2); });

    return result;
    }
    };
    基本上它归结为
  • 推导出结果数组元素类型和形状
  • 进行一元或二元变换(取决于标量/数组 rhs)

  • 现在我们可以编写程序:
    Live On Compiler Explorer
    int main() {
    using MA = boost::multi_array<int, 2>;

    auto shape = boost::extents[3][3];
    MA array1(shape), array2(shape);

    std::generate_n(array1.data(), array1.num_elements(),
    [n = 0]() mutable { return n+=100; });
    std::generate_n(array2.data(), array2.num_elements(),
    [n = 0]() mutable { return n+=1; });

    fmt::print("array1:\n\t{}\n", fmt::join(array1,"\n\t"));
    fmt::print("array2:\n\t{}\n", fmt::join(array2,"\n\t"));

    using namespace ArrayOperators;
    auto array3 = (array1 + array2)/100.0;
    fmt::print("array3:\n\t{}\n", fmt::join(array3,"\n\t"));
    }
    它打印
    array1:
    {100, 200, 300}
    {400, 500, 600}
    {700, 800, 900}
    array2:
    {1, 2, 3}
    {4, 5, 6}
    {7, 8, 9}
    array3:
    {1.01, 2.02, 3.03}
    {4.04, 5.05, 6.06}
    {7.07, 8.08, 9.09}
    但是等等,你在解决什么问题
  • 如果你想要 矩阵 (不是“数组”)操作使用 Boost uBlas、Eigen、Armadillo
  • 如果你想要最大的性能,使用 SIMD/AVX2/GPU 指令,你可以使用 Boost Compute
  • 关于c++ - 如何在两个 boost::multi_arrays (C++) 之间执行数学运算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62744851/

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