c++ - 在 C++ 中使用迭代器加速并行 std::vector 计算

标签 c++ performance iterator stdvector

我有一个小函数,它根据对基于std::vector计算的参数列表进行逐元素数学计算来计算参数。实例l,t,d,n哪里l,t,d,n都是std::vector<double> 。这是我的程序速度的关键点 - 我已经分析过,并且我确信。

这是一个使用 [] 的工作片段运算符(operator)。我正在 Core i7、8GB RAM、Windows 7 上使用 Visual C++ 2008 Express 进行 C++ 开发, Release模式为 /O2优化。最终,这将使用 SWIG 编译为 Python 扩展,但我们不要超前。

我还使用 C 数组编写了一个解决方案(见下文)(我曾经在 C 中使用的解决方案,但我已经转向 C++ 中的面向对象的解决方案,这需要(对于我的应用程序)使用 std::vector 来避免内存泄漏。)

所有三个解决方案如下。我在 SO 和其他地方听到了很多关于 std::vector 如何的讨论。迭代器解决方案应该(总是?)与数组一样快,但我的结果显示 100 万次调用需要以下时间:

  • std::vector[]运算符:2.53 s
  • std::vector使用迭代器:2.69 s
  • C 阵列:0.58 秒

很明显,数组解决方案要快得多。我在 std::vector 解决方案的编码中是否遗漏了一些明显的东西?

编辑

所以看来我的部分问题在于分析。该优化优化了我的大部分 c 数组代码,这就是为什么它比任何 std::vector 选项都要快得多。我认为我从根本上受到执行所有 exp() 和 pow() 调用的吞吐量的限制。感谢大家的所有建议,我认为对于我的应用程序,我只是在对抗处理器速度。我想 19*6 pow 调用大约 2 微秒并没有真的那么糟糕。但对我来说还是太慢了。 这就是生活...

std::vector<double>使用 [] 进行索引运算符

double phir_power::base(double tau, double delta) throw()
{
    double summer=0;
    for (unsigned int i=iStart;i<=iEnd;i++)
    {
        if (l[i]>0)
            summer+=n[i]*pow(delta,d[i])*pow(tau,t[i])*exp(-pow(delta,l[i]));
        else
            summer+=n[i]*pow(delta,d[i])*pow(tau,t[i]);
    }
    return summer;
}

std::vector<double>使用迭代器

std::vector<double>::const_iterator n_begin=n.begin(), n_end = n.end(), n_iter = n_begin;
std::vector<double>::const_iterator d_begin=d.begin(), d_end = d.end(), d_iter = d_begin;
std::vector<double>::const_iterator t_begin=t.begin(), t_end = t.end(), t_iter = t_begin;
std::vector<double>::const_iterator l_begin=l.begin(), l_end = l.end(), l_iter = l_begin;

for (unsigned int uuu=0;uuu<1e6;uuu+=1)
{
    double summer=0;
    //Bring the iterators back to the first element
    l_iter = l_begin;
    d_iter = d_begin;
    t_iter = t_begin;
    n_iter = n_begin;
    for (; l_iter != l_end; ++l_iter,++t_iter,++d_iter,++n_iter)
    {
        if ((*l_iter)>0)
            summer+=(*n_iter)*pow(delta,(*d_iter))*pow(tau,(*t_iter))*exp(-pow(delta,(*l_iter)));
        else
            summer+=(*n_iter)*pow(delta,(*d_iter))*pow(tau,(*t_iter));
    }
    rrrrrrrr += summer;
}
t2 = clock();
printf("Time for 1 million calls  %g [s] val %g \n",((double)(t2-t1))/CLOCKS_PER_SEC,rrrrrrrr);

C 数组

double r=0;
t0 = clock();
unsigned int qwe;
double ttte = 0;
double term_;
for (unsigned int j=1;j<19;j++)
{
    t1=clock();
    r=0;
    for (unsigned int i=0; i<1e6; i++)
    {
        term_ = n[j]*pow(delta,d[j])*pow(tau,t[j]);
        if (l[j]>0)
            term_ *= exp(-pow(delta,l[j]));
        r+=term_;
    }
    ttte+=r/1e6;
    t2=clock();
    printf("Index %d time %g [s] val %g\n",j,((double)(t2-t1))/CLOCKS_PER_SEC,r/1e6);
}
t3=clock();
printf("Time for 1 million calls %g [s] val is %g\n",((double)(t3-t0))/CLOCKS_PER_SEC,ttte);

最佳答案

不同之处在于,在您提供的 C 代码中,您在一个小循环内有一个大循环,其中没有任何变化,只是做了一百万次的事情。在带有迭代器的代码中,大循环内有一个小循环,这意味着它必须始终更改迭代器。这可能会花费额外的时间。我对此不确定,但如果您可以测试它:尝试一下!

关于c++ - 在 C++ 中使用迭代器加速并行 std::vector 计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11287253/

相关文章:

c++ - 在 map 中搜索值时不匹配 'operator='

c++ - 我该如何剥离符号表?

c++ - QGraphicsScene::fitInView() 仅适用于调整大小

c++ - 重载运算符以与 C++ 中的另一个类一起使用

java - 如何在更新 Oracle 中的列 Clob 时提高性能?

java - 在 Java 中使用嵌套类实现 Iterable

c++ - 为什么需要将新事件添加到 IDL 接口(interface)的*末尾*?

java - 如何确定编译器如何优化代码?

performance - Perl:为什么 if 语句比 "and"慢?

python - 如何使用 sed -n 但在 Python 中从文本文件中提取一系列行?