在布尔值数组上使用二进制表达式的最快方法
The fastest way to use a binary expression on array of booleans
我需要以最快的方式做这样的事情(0(1)将是完美的):
for (int j = 0; j < V; ++j)
{
if(!visited[j]) required[j]=0;
}
我想出了这个解决方案:
for (int j = 0; j < V; ++j)
{
required[j]=visited[j]&required[j];
}
使程序运行速度提高了3倍,但我相信有更好的方法来做到这一点。我说的对吗?
顺便说一句。Required和visited是动态分配的数组
bool *required;
bool *visited;
required = new bool[V];
visited = new bool[V];
在使用简单对象列表的情况下,最适合使用c++标准库提供的功能。像valarray和vectors这样的结构被所有现代编译器非常有效地识别和优化。
关于你能在多大程度上依赖你的编译器存在很多争论,但有一点可以保证的是,你的编译器是与标准库一起构建的,依靠它来实现基本功能(比如你的问题)通常是安全的。
永远不要害怕运行自己的时间测试和与编译器赛跑!这是一个有趣的练习,也是一个越来越难做到的练习。
构造一个valarray(在c++11和更高版本中高度优化):
std::valarray<bool> valRequired(required, V);
std::valarray<bool> valVisited(visited, V);
valRequired &= valVisited;
或者,您可以使用transform:
一行来完成它std::transform(required[0], required[V-1], visited[0], required[0], [](bool r, bool v){ return r & v; })
Edit:虽然行数少并不会更快,但编译器可能会将此操作向量化。
我还测试了他们的时间:
int main(int argc, const char * argv[]) {
auto clock = std::chrono::high_resolution_clock{};
{
bool visited[5] = {1,0,1,0,0};
bool required[5] = {1,1,1,0,1};
auto start = clock.now();
for (int i = 0; i < 5; ++i) {
required[i] &= visited[i];
}
auto end = clock.now();
std::cout << "1: " << (end - start).count() << std::endl;
}
{
bool visited[5] = {1,0,1,0,0};
bool required[5] = {1,1,1,0,1};
auto start = clock.now();
for (int i = 0; i < 5; ++i) {
required[i] = visited[i] & required[i];
}
auto end = clock.now();
std::cout << "2: " << (end - start).count() << std::endl;
}
{
bool visited[5] = {1,0,1,0,0};
bool required[5] = {1,1,1,0,1};
auto start = clock.now();
std::transform(required, required + 4, visited, required, [](bool r, bool v){ return r & v; });
auto end = clock.now();
std::cout << "3: " << (end - start).count() << std::endl;
}
{
bool visited[5] = {1,0,1,0,0};
bool required[5] = {1,1,1,0,1};
std::valarray<bool> valVisited(visited, 5);
std::valarray<bool> valrequired(required, 5);
auto start = clock.now();
valrequired &= valVisited;
auto end = clock.now();
std::cout << "4: " << (end - start).count() << std::endl;
}
}
输出:1: 102
2: 55
3: 47
4: 45
Program ended with exit code: 0
在@AlanStokes行中,使用打包的二进制数据并与AVX指令_mm512_and_epi64
结合,每次512位。做好头发乱糟糟的准备。
相关文章:
- 实现基于数字值(正、负、零)的条件表达式的最佳方法
- 用C++编写正则表达式的正确方法是什么?
- 有没有一种简单的方法来检查C++中的不安全表达式
- C++ 解决方法:"从类型"B*"的表达式初始化类型"C*&"的引用无效"
- 通过调试来检查C 中单行表达式执行顺序的方法
- 有什么方法可以通过删除表达式安全地处理两次释放内存?
- 我如何编写看起来像方法的lambda表达式
- 令牌调用之前'...'预期的主表达式 模板化类的模板化方法
- 是否存在将String转换为可执行的c++表达式的方法
- 如何使用增强正则表达式替换方法
- 在C++中匹配正则表达式的惯用方法
- 必须有一种非常快速的方法来计算此按位表达式
- 在 lambda 表达式中调用方法
- 松弛常量表达式中并集的非活动成员的左值到右值转换的解决方法
- 分配给正则表达式方法的布尔值
- 在类方法上使用指针:表达式的类型必须为bool错误
- OOP中解析S表达式的正确方法
- c++向量排序方法编译失败,返回预期表达式
- 错误:在类方法声明中无效地使用void表达式
- 用于方法链的c++ lambda表达式