C++ 将快速 1、2、3 整数映射到硬编码字符?
C++ map fast 1,2,3 integers to hardcoded chars?
我需要将 int 值 1、2、3 映射到字符 'C'、'M'、'A'
什么是最快的方式(这将在 24/7 期间每秒调用 100 次)?
一个宏或一个内联函数和一堆 ?: 运算符或 ifs 或 switch?还是数组?
A lookup-table 似乎是最明显的方法,因为它也是 branch-free:
constexpr char map(std::size_t i) {
constexpr char table[] = "0CMA";
// if in doubt add bounds checking for i, but it will cost performance
return table[i];
}
观察到通过优化,查找 table boils down 到整数常量。
编辑:如果你没有我那么懒,你可以去掉一条额外的指令,这样指定查找table:
constexpr char table[] = {0, 'M', 'C', 'A'};
我的建议:(char)(0x414D4300 >> (i * 8))
你可以写 (('C' << 8) | ('M' << 16) | ('A' << 24))
.
而不是 0x414D4300
只有实际测试才能告诉您这是否比位掩码的答案更快。
如果它每秒仅运行 100 次,那么无论如何您都是在追逐一条红鲱鱼。即使您以最愚蠢的方式编写此部分,它似乎也比程序的其余部分快一百万倍。
您正在过早地优化您的代码。让我证明一下。这是最简单、最慢但仍然合理的方法:
#include <map>
char map(int i) {
std::map<int, char> table;
table[1] = 'C';
table[2] = 'M';
table[3] = 'A';
return table[i];
}
它generates数百行汇编指令。
让我们为一百万个元素计时:
#include <iostream>
#include <map>
#include <chrono>
#include <cstdlib>
#include <vector>
char map(int i) {
std::map<int, char> table;
table[1] = 'C';
table[2] = 'M';
table[3] = 'A';
return table[i];
}
int main() {
int const count = 1'000'000;
std::vector<int> elms(count);
std::srand(0); // I know that rand is no good, but it's OK for this example
for (int i = 0; i < count; ++i) {
elms[i] = std::rand() % 3 + 1;
}
auto beg = std::chrono::high_resolution_clock::now();
volatile int do_not_optimize;
for (int i = 0; i < count; ++i) {
do_not_optimize = map(elms[i]);
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - beg);
std::cout << "Duration: " << duration.count() << " ms" << std::endl;
}
这是我电脑上的输出,旁边还有很多其他程序运行:
Duration: 246 ms
这个糟糕的实施在糟糕的条件下仍然可以满足您 40'650 倍以上的需求。我敢打赌,您在代码库的其他地方还有更多需要担心的地方。记得把它做对,只有当它还不够快时才让它变快。
我需要将 int 值 1、2、3 映射到字符 'C'、'M'、'A'
什么是最快的方式(这将在 24/7 期间每秒调用 100 次)?
一个宏或一个内联函数和一堆 ?: 运算符或 ifs 或 switch?还是数组?
A lookup-table 似乎是最明显的方法,因为它也是 branch-free:
constexpr char map(std::size_t i) {
constexpr char table[] = "0CMA";
// if in doubt add bounds checking for i, but it will cost performance
return table[i];
}
观察到通过优化,查找 table boils down 到整数常量。
编辑:如果你没有我那么懒,你可以去掉一条额外的指令,这样指定查找table:
constexpr char table[] = {0, 'M', 'C', 'A'};
我的建议:(char)(0x414D4300 >> (i * 8))
你可以写 (('C' << 8) | ('M' << 16) | ('A' << 24))
.
只有实际测试才能告诉您这是否比位掩码的答案更快。
如果它每秒仅运行 100 次,那么无论如何您都是在追逐一条红鲱鱼。即使您以最愚蠢的方式编写此部分,它似乎也比程序的其余部分快一百万倍。
您正在过早地优化您的代码。让我证明一下。这是最简单、最慢但仍然合理的方法:
#include <map>
char map(int i) {
std::map<int, char> table;
table[1] = 'C';
table[2] = 'M';
table[3] = 'A';
return table[i];
}
它generates数百行汇编指令。
让我们为一百万个元素计时:
#include <iostream>
#include <map>
#include <chrono>
#include <cstdlib>
#include <vector>
char map(int i) {
std::map<int, char> table;
table[1] = 'C';
table[2] = 'M';
table[3] = 'A';
return table[i];
}
int main() {
int const count = 1'000'000;
std::vector<int> elms(count);
std::srand(0); // I know that rand is no good, but it's OK for this example
for (int i = 0; i < count; ++i) {
elms[i] = std::rand() % 3 + 1;
}
auto beg = std::chrono::high_resolution_clock::now();
volatile int do_not_optimize;
for (int i = 0; i < count; ++i) {
do_not_optimize = map(elms[i]);
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - beg);
std::cout << "Duration: " << duration.count() << " ms" << std::endl;
}
这是我电脑上的输出,旁边还有很多其他程序运行:
Duration: 246 ms
这个糟糕的实施在糟糕的条件下仍然可以满足您 40'650 倍以上的需求。我敢打赌,您在代码库的其他地方还有更多需要担心的地方。记得把它做对,只有当它还不够快时才让它变快。