Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何优化以下常见循环?_C++_Loops_Optimization_Vectorization_Multicore - Fatal编程技术网

C++ 如何优化以下常见循环?

C++ 如何优化以下常见循环?,c++,loops,optimization,vectorization,multicore,C++,Loops,Optimization,Vectorization,Multicore,我有密码 #include <iostream> #include <vector> #include <ctime> using namespace std; void foo(int n, double* a, double* b, double *c, double*d, double* e, double* f, double* g) { for (int i = 0; i < n; ++i) a[i] = b[i] *

我有密码

#include <iostream>
#include <vector>
#include <ctime>
using namespace std;

void foo(int n, double* a, double* b, double *c, double*d, double* e, double* f, double* g)
{
    for (int i = 0; i < n; ++i)
        a[i] = b[i] * a[i] + c[i] * (d[i] + e[i] + f[i] + g[i]);
}

int main()
{
    int m = 1001001;
    vector<double> a(m), b(m), c(m), d(m), f(m);

    clock_t start = std::clock();

    for (int i = 0; i < 1000; ++i)
        foo(1000000, &a[0], &b[0], &c[0], &d[0], &d[1], &f[0], &f[1000] );

    double duration = (std::clock() - start) / (double)CLOCKS_PER_SEC;
    cout << "Finished in " << duration << " seconds [CPU Clock] " << endl;
}
#包括
#包括
#包括
使用名称空间std;
void foo(int n,double*a,double*b,double*c,double*d,double*e,double*f,double*g)
{
对于(int i=0;icout我认为您应该使用多线程。将foo更改为从index到index,而不是n,并在线程上分布向量

void foo(int fromIndex, int toIndex, double* a, double* b, double *c, double*d, double* e, double* f, double* g)
{
    for (int i = fromIndex; i < toIndex; ++i)
        a[i] = b[i] * a[i] + c[i] * (d[i] + e[i] + f[i] + g[i]);
}
void foo(int-from-index,int-to-index,double*a,double*b,double*c,double*d,double*e,double*f,double*g)
{
for(int i=fromIndex;i
我认为您应该使用多线程。将foo更改为从index获取到index,而不是n,并在线程上分布向量

void foo(int fromIndex, int toIndex, double* a, double* b, double *c, double*d, double* e, double* f, double* g)
{
    for (int i = fromIndex; i < toIndex; ++i)
        a[i] = b[i] * a[i] + c[i] * (d[i] + e[i] + f[i] + g[i]);
}
void foo(int-from-index,int-to-index,double*a,double*b,double*c,double*d,double*e,double*f,double*g)
{
for(int i=fromIndex;i
在apple clang上,我尝试了:

  • 在参数上使用
    \uuuu restict\uuuu
    ,使编译器确信没有别名
结果:没有变化

  • foo()
结果:计算时间从~3秒增加到~18秒

  • 使用
    #pragma omp parallel for
结果:编译器忽略了我,继续使用原始解决方案。~3秒

  • 设置命令行选项
    -march=native
    ,以使cpu充分发挥其强大功能
结果:不同的汇编程序输出(应用矢量化),但运行时间在~3s时仍保持不变

初步结论:


这个问题与内存访问有关,而与CPU无关。

在apple clang上,我尝试了:

  • 在参数上使用
    \uuuu restict\uuuu
    ,使编译器确信没有别名
结果:没有变化

  • foo()
结果:计算时间从~3秒增加到~18秒

  • 使用
    #pragma omp parallel for
结果:编译器忽略了我,继续使用原始解决方案。~3秒

  • 设置命令行选项
    -march=native
    ,以使cpu充分发挥其强大功能
结果:不同的汇编程序输出(应用矢量化),但运行时间在~3s时仍保持不变

初步结论:


这个问题与内存访问有关,而不是与CPU有关。

所讨论的代码是无用的。它使用未初始化的变量进行大量计算,然后忽略结果。编译器越来越擅长解决这类问题并删除所有代码。因此,如果这样的代码不可用,请不要感到惊讶我一点也不花时间

在C++中,你会把指针声明为“const double *限制”,除了一个双*限制,告诉编译器除了第一个指针之外的所有指针都指向在循环中不被修改的数据;这允许编译器进行矢量化。 如果这是您真正的问题,您只需交换内部循环和外部循环,并删除循环不变量,如下所示:

void foo(int iter, int n, double* a, double* b, double *c, double*d, double* e, double* f, double* g)
{
    for (int i = 0; i < n; ++i) {
        double xa = a [i];
        double xb = b [i];
        double xr = c[i] * (d[i] + e[i] + f[i] + g[i]);

        for (int j = 0; j < iter; ++j)
            xa = xb * xa + xr;

        a [i] = xa;
    }
}
void foo(int iter,int n,double*a,double*b,double*c,double*d,double*e,double*f,double*g)
{
对于(int i=0;i
您可能会并行执行四次迭代以避免延迟


但在现实生活中,您会发现,在每次调用中,您读取的数据约为40MB,远远超过任何缓存。因此,您受到RAM速度的限制。通常的解决方案是将工作分成更小的部分,例如一次500个元素,这样所有内容都可以放入一级缓存,然后使用相同的数据执行1000次操作。

所讨论的代码是无用的。它使用未初始化的变量进行大量计算,然后忽略结果。编译器越来越擅长解决这类问题并删除所有相关代码。因此,如果这样的代码根本不需要花费时间,请不要感到惊讶

在C++中,你会把指针声明为“const double *限制”,除了一个双*限制,告诉编译器除了第一个指针之外的所有指针都指向在循环中不被修改的数据;这允许编译器进行矢量化。 如果这是您真正的问题,您只需交换内部循环和外部循环,并删除循环不变量,如下所示:

void foo(int iter, int n, double* a, double* b, double *c, double*d, double* e, double* f, double* g)
{
    for (int i = 0; i < n; ++i) {
        double xa = a [i];
        double xb = b [i];
        double xr = c[i] * (d[i] + e[i] + f[i] + g[i]);

        for (int j = 0; j < iter; ++j)
            xa = xb * xa + xr;

        a [i] = xa;
    }
}
void foo(int iter,int n,double*a,double*b,double*c,double*d,double*e,double*f,double*g)
{
对于(int i=0;i
您可能会并行执行四次迭代以避免延迟

但在现实生活中,您会发现,在每次调用中,您读取的数据约为40MB,远远超出任何缓存。因此,您受到RAM速度的限制。通常的解决方案是将工作拆分为更小的部分,例如一次500个元素,因此所有内容