gpt4 book ai didi

c++ - 查找表与 if-else

转载 作者:可可西里 更新时间:2023-11-01 18:05:38 25 4
gpt4 key购买 nike

今天,我阅读代码时使用查找表而不是 if-else 来裁剪两个求和的 uint8 值。映射在 i={0...255} 中为 i,在 i={256...511} 中为 255。我想知道这样做的 yield 有多大,并尝试使用 gprof 找出它,

g++ -std=c++0x -pg perfLookup.cpp -O2 -o perfLookup && ./perfLookup && gprof perfLookup |less

下面附上代码。现在没有 -O2 标志,gprof 表示 lookup() 占用执行时间的 45%,而 ifelse() 占用执行时间的 48%。对于 -O2,lookup() 为 56%,ifelse() 为 43%。但这个基准真的正确吗?也许很多代码都被优化掉了,因为 dst 从未被读取过?

#include <iostream>
#include <cstdint>
#include <vector>

void lookup(std::vector<uint8_t> src, int repeat) {
uint8_t lookup[511];
for (int i = 0; i < 256; i++) {
lookup[i] = i;
}
for (int i = 256; i < 512; i++) {
lookup[i] = 255;
}

std::vector<uint8_t> dst(src.size());
for (int i = 0; i < repeat; i++) {
for (int i = 0; i < src.size(); i++) {
dst[i] = lookup[src[i]];
}
}

}

void ifelse(std::vector<uint8_t> src, int repeat) {
std::vector<uint8_t> dst(src.size());
for (int i = 0; i < repeat; i++) {
for (int i = 0; i < src.size(); i++) {
dst[i] = (src[i] > 255) ? 255 : src[i];
}
}
}

int main()
{
int n = 10000;
std::vector<uint8_t> src(n);
for (int i = 0; i < src.size(); i++) {
src[i] = rand() % 510;
}

lookup(src, 10000);
ifelse(src, 10000);
}

更新代码:

#include <iostream>
#include <cstdint>
#include <cstring>
#include <vector>
#include <algorithm>

// g++ -std=c++0x -pg perfLookup.cpp -O2 -o perfLookup && ./perfLookup && gprof perfLookup |less

std::vector<uint16_t> lookup(std::vector<uint16_t> src, int repeat) {
uint16_t lookup[511];
for (int i = 0; i < 256; i++) {
lookup[i] = i;
}
for (int i = 256; i < 511; i++) {
lookup[i] = 255;
}

std::vector<uint16_t> dst(src.size());
for (int i = 0; i < repeat; i++) {
for (int k = 0; k < src.size(); k++) {
dst[k] = lookup[src[k]];
}
}

return dst;

}

std::vector<uint16_t> ifelse(std::vector<uint16_t> src, int repeat) {
std::vector<uint16_t> dst(src.size());
for (int i = 0; i < repeat; i++) {
for (int k = 0; k < src.size(); k++) {
dst[k] = (src[k] > 255) ? 255 : src[k];
}
}
return dst;
}

std::vector<uint16_t> copyv(std::vector<uint16_t> src, int repeat) {
std::vector<uint16_t> dst(src.size());
for (int i = 0; i < repeat; i++) {
dst = src;
for (int k = 0; k < src.size(); k++) {
if (dst[k] > 255) {
dst[k] = 255;
}
}
}
return dst;
}

std::vector<uint16_t> copyC(std::vector<uint16_t> src, int repeat)
{
uint16_t* dst = (uint16_t *) malloc(sizeof(uint16_t) * src.size()); // Alloc array for dst

for (int i = 0; i < repeat; i++) {
std::memcpy(dst, &src[0], sizeof(uint16_t) * src.size()); // copy src into array

for (int k = 0; k < src.size(); k++) {
if ((dst[k] & 0xFF00) != 0)
dst[k] = 0x00FF;
}
}

free(dst);
return std::vector<uint16_t>();
}

int main()
{
int n = 10000;
std::vector<uint16_t> src(n);
for (int i = 0; i < src.size(); i++) {
src[i] = rand() % 510;
}
std::vector<uint16_t> dst;
dst = lookup(src, 10000);
dst = ifelse(src, 10000);
dst = copyv(src, 10000);
}

最佳答案

除了亚历山大已经说过的话:

查找表可以显着提高性能。但是,这被首先创建查找表所花费的时间所抵消。通常您会单独对其进行基准测试。

另一件必须记住的事情是查找表需要缓存空间,因此如果它很大可能会导致缓存未命中。如果有足够多的缓存未命中,if 方法将比查找表更快。

最后,gprof 非常适合识别瓶颈。但我不会将其用于基准测试。请改用计时功能。 gprof 使用采样,严格来说可以映射到消耗的时间,但这里不太精确。

关于c++ - 查找表与 if-else,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4783674/

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