Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.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数组的实现优于eigen?_C++_Eigen3_Economics - Fatal编程技术网

C++ 在这种情况下,为什么使用C数组的实现优于eigen?

C++ 在这种情况下,为什么使用C数组的实现优于eigen?,c++,eigen3,economics,C++,Eigen3,Economics,一套相对著名的经济学语言编码基准是由S.Borağan Aruoba和JesúS Fernández Villaverde制定的,其代码可以找到。对于C++,有两种实现随机新古典增长模型的方法,一种是使用C风格数组,另一种是用C++ STL数组。最近我一直在练习C++,因为我开始着手研究一些大规模的模型,因为语言可能是有用的(虽然我希望主要是在朱丽亚中工作),并且决定使用EGIN库创建一个变体,因为我对它的使用不太熟悉。有趣的是,我的代码使用特征比在上述链接中的两个C++程序中的任一个都慢得多。

一套相对著名的经济学语言编码基准是由S.Borağan Aruoba和JesúS Fernández Villaverde制定的,其代码可以找到。对于C++,有两种实现随机新古典增长模型的方法,一种是使用C风格数组,另一种是用C++ STL数组。最近我一直在练习C++,因为我开始着手研究一些大规模的模型,因为语言可能是有用的(虽然我希望主要是在朱丽亚中工作),并且决定使用EGIN库创建一个变体,因为我对它的使用不太熟悉。有趣的是,我的代码使用特征比在上述链接中的两个C++程序中的任一个都慢得多。我的假设是,这是由于我的实现很差,这个问题太简单,由于它增加了开销,所以Eigen不值得使用,但是我想问这个假设是否正确

我使用eigen的代码是:

#include <chrono>
#include <iostream>
#include <Eigen/Dense>
#include <cmath>

int main()
{
    //---------------------------------------------------------------------------------------------------
    //Timer Start
    const auto time_0 = std::chrono::steady_clock::now();
    //---------------------------------------------------------------------------------------------------
    //Parameter Declaration
    const double aalpha = 0.33333333333;     // Elasticity of output w.r.t. capital
    const double bbeta = 0.95;              // Discount factor;

    const size_t nGridProductivity = 5;
    Eigen::Matrix<double, nGridProductivity, 1> vProductivity;
    vProductivity << 0.9792, 0.9896, 1.0000, 1.0106, 1.0212;

    Eigen::Matrix<double, nGridProductivity, nGridProductivity> mTransition;
    mTransition << 0.9727, 0.0273, 0.0000, 0.0000, 0.0000,
                   0.0041, 0.9806, 0.0153, 0.0000, 0.0000,
                   0.0000, 0.0082, 0.9837, 0.0082, 0.0000,
                   0.0000, 0.0000, 0.0153, 0.9806, 0.0041,
                   0.0000, 0.0000, 0.0000, 0.0273, 0.9727;
    //---------------------------------------------------------------------------------------------------
    // Steady State
    const double capitalSteadyState = std::pow(aalpha * bbeta, 1. / (1. - aalpha));
    const double outputSteadyState = std::pow(capitalSteadyState, aalpha);
    const double consumptionSteadyState = outputSteadyState - capitalSteadyState;

    std::cout << "Output = " << outputSteadyState << ", Capital = " << capitalSteadyState << ", Consumption = " << consumptionSteadyState << "\n";
    std::cout << " ";


    // Capital Grid
    const int nGridCapital = 17820;
    
    Eigen::VectorXd vGridCapital(nGridCapital);
    vGridCapital.setLinSpaced(nGridCapital, 0.5 * capitalSteadyState, 1.5 * capitalSteadyState); 
    //---------------------------------------------------------------------------------------------------
    //Required Matrices and Vectors

    Eigen::MatrixXd mOutput(nGridCapital, nGridProductivity);
    Eigen::MatrixXd mValueFunction (nGridCapital, nGridProductivity);
    mValueFunction.setZero();//Need to initialise to zero for first iteration
    Eigen::MatrixXd mValueFunctionNew(nGridCapital, nGridProductivity);
    mValueFunctionNew.setZero();
    Eigen::MatrixXd mPolicyFunction(nGridCapital, nGridProductivity);
    mPolicyFunction.setZero();
    Eigen::MatrixXd expectedValueFunction(nGridCapital, nGridProductivity);


    //---------------------------------------------------------------------------------------------------
    //Pre-Build Output
    mOutput = (vGridCapital.array().pow(aalpha).matrix()) * vProductivity.transpose();
    std::cout << "Test mOutput" << mOutput(2, 2) << std::endl;
    //---------------------------------------------------------------------------------------------------
    //Main Iteration

    const double tolerance = 0.0000001;
    double maxDifference = 10.0;
    std::size_t iteration = 0;

    while (maxDifference > tolerance)
    {
        expectedValueFunction = mValueFunction * mTransition.transpose();

        for (std::size_t nProductivity = 0; nProductivity < nGridProductivity; ++nProductivity)
        {
            // We start from previous choice (monotonicity of policy function)
            std::size_t gridCapitalNextPeriod = 0;
            for (std::size_t nCapital = 0; nCapital < nGridCapital; ++nCapital)
            {
                double valueHighSoFar = -100000.0;
                double capitalChoice = vGridCapital(0);

                for (std::size_t nCapitalNextPeriod = gridCapitalNextPeriod; nCapitalNextPeriod < nGridCapital; ++nCapitalNextPeriod)
                {
                    const double consumption = mOutput(nCapital, nProductivity) - vGridCapital(nCapitalNextPeriod);
                    const double valueProvisional = (1. - bbeta) * std::log(consumption) + bbeta * expectedValueFunction(nCapitalNextPeriod, nProductivity);
                    if (valueProvisional > valueHighSoFar)
                    {
                        valueHighSoFar = valueProvisional;
                        capitalChoice = vGridCapital(nCapitalNextPeriod);
                        gridCapitalNextPeriod = nCapitalNextPeriod;
                    }
                    else
                    {
                        mValueFunctionNew(nCapital, nProductivity) = valueHighSoFar;
                        mPolicyFunction(nCapital, nProductivity) = capitalChoice;
                        // We break when we have achieved the max (note: of a monotonic function)
                        break;
                    }
                    mValueFunctionNew(nCapital, nProductivity) = valueHighSoFar;
                    mPolicyFunction(nCapital, nProductivity) = capitalChoice;
                }
            }
        }


        maxDifference = (mValueFunctionNew - mValueFunction).cwiseAbs().maxCoeff();
        mValueFunction = mValueFunctionNew;

        ++iteration;
        if ((iteration % 10 == 0) || (iteration == 1))
            std::cout << "Iteration = " << iteration << ", Sup Diff = " << maxDifference << "\n";
    }

    std::cout << "Iteration = " << iteration << ", Sup Diff = " << maxDifference << "\n";
    endl(std::cout);
    std::cout << "My check = " << mPolicyFunction(999, 2) << "\n";
    endl(std::cout);

    //---------------------------------------------------------------------------------------------------
    //Timer End
    const auto time_1 = std::chrono::steady_clock::now();
    const auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(time_1 - time_0).count();
    std::cout << "Elapsed time is   = " << elapsed_seconds << " seconds." << std::endl;
    endl(std::cout);

    return 0;
}
#包括
#包括
#包括
#包括
int main()
{
//---------------------------------------------------------------------------------------------------
//定时器启动
const auto time_0=std::chrono::staid_clock::now();
//---------------------------------------------------------------------------------------------------
//参数声明
const double aalpha=0.33333;//产出与资本的弹性
常数双bbeta=0.95;//折扣系数;
常数大小=5;
特征::矩阵乘积;

这里的生产率只是一个猜测,但您的算法似乎使用了元素操作(如索引矩阵/向量)。我的猜测是库优化的块操作(向量/矩阵乘法等)。通常在您希望使块操作快速进行时更改元素,如果您只是处理常规数组,则不需要更改额外数据。您可以尝试在禁用断言的情况下进行编译(应使用MSVC进行
/NDEBUG
)--在确保代码正确运行后。但MSVC有时在内联某些特征方法时仍然存在问题,因此如果无法切换到clang或gcc,则可能需要承受一些开销。在这里冒险猜测一下,但您的算法似乎使用了元素操作(如索引矩阵/向量)。我猜是库优化的块操作(向量/矩阵乘法等)。通常在您想要使块操作快速时更改元素,如果您只是处理常规数组,则不需要更改额外数据。您可以尝试在禁用断言的情况下编译(应该是MSVC的
/NDEBUG
)——在确保代码正确运行后。但MSVC有时在内联某些特征方法时仍然存在问题,因此如果无法切换到clang或gcc,您可能不得不承受一些开销。