gpt4 book ai didi

c++ - 优化for循环的函数调用

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:11:01 25 4
gpt4 key购买 nike

我有一些简单的功能

int f_0(int);
int f_1(int);
...
int f_n(int);

然后我有一些 for 循环,我在其中调用 f_i(),这个循环中的条件不必相同

for (int i = 0; i < n; i++) {
...
if (condition) {
int myInt = f_i(); // this is not real implementation but shows the result
// I want to achieve
... //edit
}
...
}

以下是我尝试实现的方法:

  • 分解 for 循环并调用相应部分中的每个函数。这会产生最快的代码,但这非常不优雅,而且这样的代码很难进一步开发。
  • 函数指针

    typedef int (*Foo) (int);

    Foo fptr[] = { f_0, f_1, ... , f_n };

这是一个优雅的方法,但在我的例子中,它比分解循环慢 4.4。指向函数的常量指针产生类似的结果。

  • 将我的功能封装到开关功能中。这比打破循环慢 2.6。

有没有更好的方法来实现这个? 理想的解决方案是代码紧凑但编译器会分解循环并让计算速度最快的解决方案。

我使用 MSVC 2012 并在 Release模式下运行,优化设置为最大化速度。

编辑:

这是我的测试代码:

头.h

namespace c {
const int w = 1024;
const int A = w * w;
}

inline int f_0(int pos) { return (pos - c::w + c::A) % c::A; }
inline int f_1(int pos) { return (pos + 1 - c::w + c::A) % c::A; }
inline int f_2(int pos) { return (pos + 1) % c::A; }
inline int f_3(int pos) { return (pos + c::w) % c::A; }
inline int f_4(int pos) { return (pos - 1 + c::w) % c::A; }
inline int f_5(int pos) { return (pos - 1 + c::A) % c::A; }

typedef int (*NEIGH_F) (int);
typedef int (* const CNEIGH_F) (int);

const NEIGH_F fptr[] = { f_0, f_1, f_2, f_3, f_4, f_5 };
const CNEIGH_F cfptr[] = { f_0, f_1, f_2, f_3, f_4, f_5 };

inline int fswitch(int i, int pos) {
switch(i) {
case 0 : return f_0(pos); break;
case 1 : return f_1(pos); break;
case 2 : return f_2(pos); break;
case 3 : return f_3(pos); break;
case 4 : return f_4(pos); break;
case 5 : return f_5(pos); break;
default : return -1; break;
}
}

主要.cpp

#include "head.h"
#include <iostream>
#include <time.h>

int main()
{
int maxRepeat = 100;

clock_t startTime = clock();
double sum = 0;
for (int repeat = 0; repeat < maxRepeat; repeat++)
for (int i = 0; i < c::A; i++) {
sum += f_0(i);
sum += f_1(i);
sum += f_2(i);
sum += f_3(i);
sum += f_4(i);
sum += f_5(i);
}
std::cout << "normal time: " << (clock() - startTime)/(double)CLOCKS_PER_SEC
<< " sum is: " << sum << std::endl;

startTime = clock();
sum = 0;
for (int repeat = 0; repeat < maxRepeat; repeat++)
for (int i = 0; i < c::A; i++) {
for (int j = 0; j < 6; j++)
sum += fptr[j](i);
}
std::cout << "pointer time: " << (clock() - startTime)/(double)CLOCKS_PER_SEC
<< " sum is: " << sum << std::endl;

startTime = clock();
sum = 0;
for (int repeat = 0; repeat < maxRepeat; repeat++)
for (int i = 0; i < c::A; i++) {
for (int j = 0; j < 6; j++)
sum += cfptr[j](i);
}
std::cout << "const pointer time: " << (clock() - startTime)/(double)CLOCKS_PER_SEC
<< " sum is: " << sum << std::endl;

startTime = clock();
sum = 0;
for (int repeat = 0; repeat < maxRepeat; repeat++)
for (int i = 0; i < c::A; i++) {
for (int j = 0; j < 6; j++)
sum += fswitch(j, i);
}
std::cout << "switch time: " << (clock() - startTime)/(double)CLOCKS_PER_SEC
<< " sum is: " << sum << std::endl;
std::cin.ignore();

return 0;
}

函数 f_i 是我在实际实现中使用的函数,但由于实际实现中的测试目的,这里的循环要简单得多,问题的第二个代码片段中显示了几个不同形式的循环。

编辑2:

我的循环形式应该保持不变我只是想找到将 f_i 放入我的循环中的最佳方法。

最佳答案

您可以使用模板函数代替 f_0 , f_1 ...更好维护。

template <int N>
void f();

template <>
void f<0>()
{
printf("f<0>");
}

template <>
void f<1>()
{
printf("f<1>");
}

int main() {
f<0>();
f<1>();
//f<2>(); // this is compile error
return 0;
}

但是,模板参数必须作为编译时常量提供,因此您不能调用类似int i = 0; f<i>() 的函数。

要解决这个问题,您可以使用 switch-case 来调用函数,不是很漂亮,但是可以用

void call_f(int i)
{
switch(i)
{
case 0:
f<0>();
break;
case 1:
f<1>();
break;
default:
// invalid i, report error
break;
}
}

然而,没有编译时检查i

put all together

关于c++ - 优化for循环的函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19779506/

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