如何在没有冗余计算的if语句中使用std::valarray?
How to use std::valarray in if statement without redundant computation?
我有以下代码 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<float>
替换 float
:
using vfloat = std::valarray<float>;
std::vector<vfloat> v = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.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
而不进行冗余计算呢?
有很多选择:
#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();
}
如果您想跳过 v[i]
中的元素,请使用嵌套循环
using vfloat = std::valarray<float>;
std::vector<vfloat> v = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.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 = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.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 = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.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.
我有以下代码 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<float>
替换 float
:
using vfloat = std::valarray<float>;
std::vector<vfloat> v = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.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
而不进行冗余计算呢?
有很多选择:
#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();
}
如果您想跳过 v[i]
中的元素,请使用嵌套循环
using vfloat = std::valarray<float>;
std::vector<vfloat> v = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.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 = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.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 = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.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.