代码之家  ›  专栏  ›  技术社区  ›  kingledion

如果我运行循环一百万次,我是否需要担心在每次迭代中声明double?

  •  3
  • kingledion  · 技术社区  · 7 年前

    我循环了一百万次。在循环中,我调用一个C函数进行一些数学运算(确切地说,从各种分布中生成随机变量)。作为该函数的一部分,我声明了 double 用于保存部分转换的变量。例如:

    void getRandNorm(double *randnorm, double mean, double var, int n) 
    {
        // Declare variables
        double u1;
        double u2;
        int arrptr = 0;
        double sigma = sqrt(var); // the standard deviation
    
        while (arrptr < n) { 
            // Generate two uniform random variables
            u1 = rand() / (double)RAND_MAX;
            u2 = rand() / (double)RAND_MAX;
    
            // Box-Muller transform
            randnorm[arrptr] = sqrt(-2*log(u1))*cos(2*pi*u2)*sigma+mean;
            arrptr++;
            if (arrptr < n) { // for an odd n, we cannot add off the end
                randnorm[arrptr] = sqrt(-2*log(u2))*cos(2*pi*u1)*sigma+mean;
                arrptr++;
            }
        }   
    }
    

    以及调用循环:

    iter = 1000000 // or something
    for (i = 0; i < iter; i++) {
    
        // lots of if statements
        getRandNorm(sample1, truemean1, truevar1, n);
    
        // some more analysis
    }
    

    我正在努力提高运行速度。我突然意识到,我不知道这一切发生了什么 双重的 我声明的变量。我假设为100万个循环中的每个循环分配了一个新的8字节内存块。所有这些内存位置会发生什么情况?它们在C函数中声明;它们能在这种功能下存活下来吗?在脚本退出之前,它们是否仍被锁定?

    这个问题的上下文是将这个C程序包装到python函数中。如果我要从python并行多次执行此函数,我想确保我在内存使用方面尽可能节约。

    3 回复  |  直到 7 年前
        1
  •  3
  •   C_Elegans    7 年前

    如果你在谈论这样的事情:

    for(int i=0;i<100000;i++){
        double d = 5;
        // some other stuff here
    }
    

    d 编译器只分配一次。它基本上相当于在for循环之上声明它,只是范围没有扩展到那么远。

    但是,如果您正在执行以下操作:

    for(int i=0;i<1000000;i++){
        double *d = malloc(sizeof(double));
        free(d);
    }
    

    那么是的,您将分配 double 100万次,但它可能会重新使用内存进行后续分配。最后,在我的第二个示例中,如果不释放内存,将泄漏16-32MB内存。

        2
  •  2
  •   chqrlie    7 年前

    简单的回答是: ,如果你申报这些应该没关系 double C中循环内的变量 双重的 变量,我想你是指 双重的

    答案很长:请发布您的代码,这样人们就可以告诉您是否做错了什么,以及如何修复它以提高正确性和/或性能(这是一个广泛的主题)。

    最后的答案是:有了提供的代码,您是否声明 u1 u2 环体内部或外部。一个好的编译器可能会生成相同的代码。

    只需测试一次奇怪的情况,就可以稍微改进代码:

    void getRandNorm(double *randnorm, double mean, double var, int n, double pi) {
        // Declare variables
        double u1, u2;
        double sigma = sqrt(var); // the standard deviation
        int arrptr, odd;
    
        odd = n & 1;  // check if n is odd
        n -= odd;     // make n even
    
        for (arrptr = 0; arrptr < n; arrptr += 2) { 
            // Generate two uniform random variables
            u1 = rand() / (double)RAND_MAX;
            u2 = rand() / (double)RAND_MAX;
    
            // Box-Muller transform
            randnorm[arrptr + 0] = sqrt(-2*log(u1)) * cos(2*pi*u2) * sigma + mean;
            randnorm[arrptr + 1] = sqrt(-2*log(u2)) * cos(2*pi*u1) * sigma + mean;
        }
        if (odd) {
            u1 = rand() / (double)RAND_MAX;
            u2 = rand() / (double)RAND_MAX;
            randnorm[arrptr++] = sqrt(-2*log(u1)) * cos(2*pi*u2) * sigma + mean;
        }
    }
    

    注: arrptr + 0 是为了对称,编译器不会为此添加生成任何代码。

        3
  •  1
  •   user3629249    7 年前

    关于您的问题: 如果我运行循环一百万次,我是否需要担心在每次迭代中声明double?

    正在堆栈上声明变量。因此,当函数退出时,它们会“消失”。函数的下一次执行将“重新创建”变量,因此(实际上)只有一个变量实例,即使如此,也只有在函数执行时。

    因此,调用函数的次数无关紧要。