00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "Sacado_Random.hpp"
00033 #include "Sacado.hpp"
00034
00035 #include "Fad/fad.h"
00036 #include "TinyFadET/tfad.h"
00037
00038 #include "Teuchos_Time.hpp"
00039 #include "Teuchos_CommandLineProcessor.hpp"
00040
00041
00042
00043
00044 template <>
00045 Sacado::Fad::MemPool* Sacado::Fad::MemPoolStorage<double>::defaultPool_ = NULL;
00046
00047 void FAD::error(const char *msg) {
00048 std::cout << msg << std::endl;
00049 }
00050
00051 template <typename T>
00052 inline void
00053 func1(const T& x1, const T& x2, T& y) {
00054 y = (x1*x2 + sin(x1)/x2);
00055 }
00056
00057 inline void
00058 func1_and_deriv(int n, double x1, double x2, double* x1dot, double* x2dot,
00059 double& y, double* ydot) {
00060 double s = sin(x1);
00061 double c = cos(x1);
00062 double t = s/x2;
00063 double t1 = x2 + c/x2;
00064 double t2 = x1 - t/x2;
00065 y = x1*x2 + t;
00066 for (int i=0; i<10; i++)
00067 ydot[i] = t1*x1dot[i] + t2*x2dot[i];
00068 }
00069
00070 template <typename FadType>
00071 double
00072 do_time(int nderiv, int nloop)
00073 {
00074 FadType x1, x2, y;
00075 Sacado::Random urand(0.0, 1.0);
00076
00077 x1 = FadType(nderiv, urand.number());
00078 x2 = FadType(nderiv, urand.number());
00079 y = 0.0;
00080 for (int j=0; j<nderiv; j++) {
00081 x1.fastAccessDx(j) = urand.number();
00082 x2.fastAccessDx(j) = urand.number();
00083 }
00084
00085 Teuchos::Time timer("mult", false);
00086 timer.start(true);
00087 for (int j=0; j<nloop; j++) {
00088 func1(x1, x2, y);
00089 }
00090 timer.stop();
00091
00092 return timer.totalElapsedTime() / nloop;
00093 }
00094
00095 double
00096 do_time_analytic(int nderiv, int nloop)
00097 {
00098 double x1, x2, y;
00099 double *x1dot, *x2dot, *ydot;
00100 Sacado::Random urand(0.0, 1.0);
00101
00102 x1 = urand.number();
00103 x2 = urand.number();
00104 y = 0.0;
00105 x1dot = new double[nderiv];
00106 x2dot = new double[nderiv];
00107 ydot = new double[nderiv];
00108 for (int j=0; j<nderiv; j++) {
00109 x1dot[j] = urand.number();
00110 x2dot[j] = urand.number();
00111 }
00112
00113 Teuchos::Time timer("mult", false);
00114 timer.start(true);
00115 for (int j=0; j<nloop; j++) {
00116 func1_and_deriv(nderiv, x1, x2, x1dot, x2dot, y, ydot);
00117 }
00118 timer.stop();
00119
00120 return timer.totalElapsedTime() / nloop;
00121 }
00122
00123 int main(int argc, char* argv[]) {
00124 int ierr = 0;
00125
00126 try {
00127 double t, ta;
00128 int p = 2;
00129 int w = p+7;
00130
00131
00132 Teuchos::CommandLineProcessor clp;
00133 clp.setDocString("This program tests the speed of various forward mode AD implementations for a single multiplication operation");
00134 int nderiv = 10;
00135 clp.setOption("nderiv", &nderiv, "Number of derivative components");
00136 int nloop = 1000000;
00137 clp.setOption("nloop", &nloop, "Number of loops");
00138
00139
00140 Teuchos::CommandLineProcessor::EParseCommandLineReturn
00141 parseReturn= clp.parse(argc, argv);
00142 if(parseReturn != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL)
00143 return 1;
00144
00145
00146 Sacado::Fad::MemPoolManager<double> poolManager(10);
00147 Sacado::Fad::MemPool* pool = poolManager.getMemoryPool(nderiv);
00148 Sacado::Fad::DMFad<double>::setDefaultPool(pool);
00149
00150 std::cout.setf(std::ios::scientific);
00151 std::cout.precision(p);
00152 std::cout << "Times (sec) for nderiv = " << nderiv
00153 << " nloop = " << nloop << ": " << std::endl;
00154
00155 ta = do_time_analytic(nderiv, nloop);
00156 std::cout << "Analytic: " << std::setw(w) << ta << std::endl;
00157
00158 t = do_time< FAD::TFad<10,double> >(nderiv, nloop);
00159 std::cout << "TFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00160
00161 t = do_time< FAD::Fad<double> >(nderiv, nloop);
00162 std::cout << "Fad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00163
00164 t = do_time< Sacado::Fad::SFad<double,10> >(nderiv, nloop);
00165 std::cout << "SFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00166
00167 t = do_time< Sacado::Fad::SLFad<double,10> >(nderiv, nloop);
00168 std::cout << "SLFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00169
00170 t = do_time< Sacado::Fad::DFad<double> >(nderiv, nloop);
00171 std::cout << "DFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00172
00173 t = do_time< Sacado::Fad::DMFad<double> >(nderiv, nloop);
00174 std::cout << "DMFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00175
00176 t = do_time< Sacado::ELRFad::SFad<double,10> >(nderiv, nloop);
00177 std::cout << "ELRSFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00178
00179 t = do_time< Sacado::ELRFad::SLFad<double,10> >(nderiv, nloop);
00180 std::cout << "ELRSLFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00181
00182 t = do_time< Sacado::ELRFad::DFad<double> >(nderiv, nloop);
00183 std::cout << "ELRDFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00184
00185 t = do_time< Sacado::CacheFad::DFad<double> >(nderiv, nloop);
00186 std::cout << "CacheFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00187
00188 }
00189 catch (std::exception& e) {
00190 cout << e.what() << endl;
00191 ierr = 1;
00192 }
00193 catch (const char *s) {
00194 cout << s << endl;
00195 ierr = 1;
00196 }
00197 catch (...) {
00198 cout << "Caught unknown exception!" << endl;
00199 ierr = 1;
00200 }
00201
00202 return ierr;
00203 }