如何在没有冗余计算的 if 语句中使用 std::valarray?

Posted

技术标签:

【中文标题】如何在没有冗余计算的 if 语句中使用 std::valarray?【英文标题】:How to use std::valarray in if statement without redundant computation? 【发布时间】:2020-05-31 15:09:44 【问题描述】:

我有以下带有float的代码,例如:

std::vector<float> v = 0.f, 1.f, 2.f;
for(size_t i = 0; i < v.size(); ++i)
    if(v[i] != 0) // An optimization for `v[i] != 0`.
        v[i] = v[i] * v[i] * v[i]; // Time-consuming computation.

现在我想用std::valarray&lt;float&gt;替换float

using vfloat = std::valarray<float>;
std::vector<vfloat> v = vfloat0.f, 0.f, vfloat1.f, 0.f, vfloat2.f, 0.f;
for(size_t i = 0; i < v.size(); ++i)
    // if(v[i] != 0) // I want this optimization! ◀◀◀◄◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀
        v[i] = v[i] * v[i] * v[i]; // Time-consuming computation.

虽然新代码在逻辑上是正确的,但对于v[i][j] == 0存在冗余计算。

那么如何在if语句中使用std::valarray而不进行冗余计算呢?

【问题讨论】:

“最佳”以什么方式?你面临什么问题?澄清。 你真的要开启警告 @AsteroidsWithWings 抱歉不清楚。现已更新。 使用嵌套循环 如果你问如何检查一个 valarray 是否包含非零元素:if ((v0[i] != 0).max()) 【参考方案1】:

如果您想跳过 v[i] 中的元素,请使用嵌套循环

using vfloat = std::valarray<float>;
std::vector<vfloat> v = vfloat0.f, 0.f, vfloat1.f, 0.f, vfloat2.f, 0.f;
for(size_t i = 0; i < v.size(); ++i)
    for(size_t j = 0; j < v[i].size(); ++j)
        if (v[i][j] != 0)
            v[i][j] = v[i][j] * v[i][j] * v[i][j]; // Time-consuming computation.

apply:

using vfloat = std::valarray<float>;
std::vector<vfloat> v = vfloat0.f, 0.f, vfloat1.f, 0.f, vfloat2.f, 0.f;
for(size_t i = 0; i < v.size(); ++i)
    v[i] = v[i].apply([](float n) -> float 
        if (n == 0) return 0;
        return n * n * n; // Time-consuming computation.
    );

如果你想跳过v中的元素

using vfloat = std::valarray<float>;
std::vector<vfloat> v = vfloat0.f, 0.f, vfloat1.f, 0.f, vfloat2.f, 0.f;
for(size_t i = 0; i < v.size(); ++i)
    if ((v[i] != 0).max() != 0)
        v[i] = v[i] * v[i] * v[i]; // Time-consuming computation.

【讨论】:

【参考方案2】:

有很多选择:

#include <valarray>
#include <algorithm>
// 2 loops in the worst case 
bool is_not_zero_0(std::valarray<float> const & v)

    return v.max() != 0.0 || v.min() != 0.0;


// one loop
bool is_not_zero_1(std::valarray<float> const & v)

    return std::find_if(v.begin(), v.end(v), [](float item)return item != 0.0f;) != v.end();

// 2 loops + allocation
bool is_not_zero_2(std::valarray<float> const & v)

    return (v != 0.0).max();

【讨论】:

以上是关于如何在没有冗余计算的 if 语句中使用 std::valarray?的主要内容,如果未能解决你的问题,请参考以下文章

Javascript if语句双感叹号运算符冗余[重复]

C++ 在 if 语句中使用 char

C ++如何一起使用 std::adjacent 和 std::count_if 来计算向量中条件的出现次数

在基本C编程中使用“If语句”。我该如何正确格式化它们?

可以一学的代码优化小技巧:减少if-else冗余

在 Laravel 中如何使用 if 语句停止计算?