CudaMechanicalObject.inl

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #ifndef SOFA_GPU_CUDA_CUDAMECHANICALOBJECT_INL
00026 #define SOFA_GPU_CUDA_CUDAMECHANICALOBJECT_INL
00027 
00028 #include "CudaMechanicalObject.h"
00029 #include <sofa/component/MechanicalObject.inl>
00030 
00031 
00032 namespace sofa
00033 {
00034 
00035 namespace gpu
00036 {
00037 
00038 namespace cuda
00039 {
00040 
00041 extern "C"
00042 {
00043 void MechanicalObjectCudaVec3f_vAssign(unsigned int size, void* res, const void* a);
00044 void MechanicalObjectCudaVec3f_vClear(unsigned int size, void* res);
00045 void MechanicalObjectCudaVec3f_vMEq(unsigned int size, void* res, float f);
00046 void MechanicalObjectCudaVec3f_vEqBF(unsigned int size, void* res, const void* b, float f);
00047 void MechanicalObjectCudaVec3f_vPEq(unsigned int size, void* res, const void* a);
00048 void MechanicalObjectCudaVec3f_vPEqBF(unsigned int size, void* res, const void* b, float f);
00049 void MechanicalObjectCudaVec3f_vAdd(unsigned int size, void* res, const void* a, const void* b);
00050 void MechanicalObjectCudaVec3f_vOp(unsigned int size, void* res, const void* a, const void* b, float f);
00051 void MechanicalObjectCudaVec3f_vIntegrate(unsigned int size, const void* a, void* v, void* x, float f_v_v, float f_v_a, float f_x_x, float f_x_v);
00052 void MechanicalObjectCudaVec3f_vPEqBF2(unsigned int size, void* res1, const void* b1, float f1, void* res2, const void* b2, float f2);
00053 void MechanicalObjectCudaVec3f_vPEq4BF2(unsigned int size, void* res1, const void* b11, float f11, const void* b12, float f12, const void* b13, float f13, const void* b14, float f14,
00054                                                            void* res2, const void* b21, float f21, const void* b22, float f22, const void* b23, float f23, const void* b24, float f24);
00055 void MechanicalObjectCudaVec3f_vOp2(unsigned int size, void* res1, const void* a1, const void* b1, float f1, void* res2, const void* a2, const void* b2, float f2);
00056 int MechanicalObjectCudaVec3f_vDotTmpSize(unsigned int size);
00057 void MechanicalObjectCudaVec3f_vDot(unsigned int size, float* res, const void* a, const void* b, void* tmp, float* cputmp);
00058 void MechanicalObjectCudaVec3f1_vAssign(unsigned int size, void* res, const void* a);
00059 void MechanicalObjectCudaVec3f1_vClear(unsigned int size, void* res);
00060 void MechanicalObjectCudaVec3f1_vMEq(unsigned int size, void* res, float f);
00061 void MechanicalObjectCudaVec3f1_vEqBF(unsigned int size, void* res, const void* b, float f);
00062 void MechanicalObjectCudaVec3f1_vPEq(unsigned int size, void* res, const void* a);
00063 void MechanicalObjectCudaVec3f1_vPEqBF(unsigned int size, void* res, const void* b, float f);
00064 void MechanicalObjectCudaVec3f1_vAdd(unsigned int size, void* res, const void* a, const void* b);
00065 void MechanicalObjectCudaVec3f1_vOp(unsigned int size, void* res, const void* a, const void* b, float f);
00066 void MechanicalObjectCudaVec3f1_vIntegrate(unsigned int size, const void* a, void* v, void* x, float f_v_v, float f_v_a, float f_x_x, float f_x_v);
00067 void MechanicalObjectCudaVec3f1_vPEqBF2(unsigned int size, void* res1, const void* b1, float f1, void* res2, const void* b2, float f2);
00068 void MechanicalObjectCudaVec3f1_vPEq4BF2(unsigned int size, void* res1, const void* b11, float f11, const void* b12, float f12, const void* b13, float f13, const void* b14, float f14,
00069                                                             void* res2, const void* b21, float f21, const void* b22, float f22, const void* b23, float f23, const void* b24, float f24);
00070 void MechanicalObjectCudaVec3f1_vOp2(unsigned int size, void* res1, const void* a1, const void* b1, float f1, void* res2, const void* a2, const void* b2, float f2);
00071 int MechanicalObjectCudaVec3f1_vDotTmpSize(unsigned int size);
00072 void MechanicalObjectCudaVec3f1_vDot(unsigned int size, float* res, const void* a, const void* b, void* tmp, float* cputmp);
00073 
00074 
00075 } // extern "C"
00076 
00077 template<>
00078 class CudaKernelsMechanicalObject<CudaVec3fTypes>
00079 {
00080 public:
00081     static void vAssign(unsigned int size, void* res, const void* a)
00082     {   MechanicalObjectCudaVec3f_vAssign(size, res, a); }
00083     static void vClear(unsigned int size, void* res)
00084     {   MechanicalObjectCudaVec3f_vClear(size, res); }
00085     static void vMEq(unsigned int size, void* res, float f)
00086     {   MechanicalObjectCudaVec3f_vMEq(size, res, f); }
00087     static void vEqBF(unsigned int size, void* res, const void* b, float f)
00088     {   MechanicalObjectCudaVec3f_vEqBF(size, res, b, f); }
00089     static void vPEq(unsigned int size, void* res, const void* a)
00090     {   MechanicalObjectCudaVec3f_vPEq(size, res, a); }
00091     static void vPEqBF(unsigned int size, void* res, const void* b, float f)
00092     {   MechanicalObjectCudaVec3f_vPEqBF(size, res, b, f); }
00093     static void vAdd(unsigned int size, void* res, const void* a, const void* b)
00094     {   MechanicalObjectCudaVec3f_vAdd(size, res, a, b); }
00095     static void vOp(unsigned int size, void* res, const void* a, const void* b, float f)
00096     {   MechanicalObjectCudaVec3f_vOp(size, res, a, b, f); }
00097     static void vIntegrate(unsigned int size, const void* a, void* v, void* x, float f_v_v, float f_v_a, float f_x_x, float f_x_v)
00098     {   MechanicalObjectCudaVec3f_vIntegrate(size, a, v, x, f_v_v, f_v_a, f_x_x, f_x_v); }
00099     static void vPEqBF2(unsigned int size, void* res1, const void* b1, float f1, void* res2, const void* b2, float f2)
00100     {   MechanicalObjectCudaVec3f_vPEqBF2(size, res1, b1, f1, res2, b2, f2); }
00101     static void vPEq4BF2(unsigned int size, void* res1, const void* b11, float f11, const void* b12, float f12, const void* b13, float f13, const void* b14, float f14,
00102                                             void* res2, const void* b21, float f21, const void* b22, float f22, const void* b23, float f23, const void* b24, float f24)
00103     {   MechanicalObjectCudaVec3f_vPEq4BF2(size, res1, b11, f11, b12, f12, b13, f13, b14, f14,
00104                                                  res2, b21, f21, b22, f22, b23, f23, b24, f24); }
00105     static void vOp2(unsigned int size, void* res1, const void* a1, const void* b1, float f1, void* res2, const void* a2, const void* b2, float f2)
00106     {   MechanicalObjectCudaVec3f_vOp2(size, res1, a1, b1, f1, res2, a2, b2, f2); }
00107     static int vDotTmpSize(unsigned int size)
00108     {   return MechanicalObjectCudaVec3f_vDotTmpSize(size); }
00109     static void vDot(unsigned int size, float* res, const void* a, const void* b, void* tmp, float* cputmp)
00110     {   MechanicalObjectCudaVec3f_vDot(size, res, a, b, tmp, cputmp); }
00111 };
00112 
00113 template<>
00114 class CudaKernelsMechanicalObject<CudaVec3f1Types>
00115 {
00116 public:
00117     static void vAssign(unsigned int size, void* res, const void* a)
00118     {   MechanicalObjectCudaVec3f1_vAssign(size, res, a); }
00119     static void vClear(unsigned int size, void* res)
00120     {   MechanicalObjectCudaVec3f1_vClear(size, res); }
00121     static void vMEq(unsigned int size, void* res, float f)
00122     {   MechanicalObjectCudaVec3f1_vMEq(size, res, f); }
00123     static void vEqBF(unsigned int size, void* res, const void* b, float f)
00124     {   MechanicalObjectCudaVec3f1_vEqBF(size, res, b, f); }
00125     static void vPEq(unsigned int size, void* res, const void* a)
00126     {   MechanicalObjectCudaVec3f1_vPEq(size, res, a); }
00127     static void vPEqBF(unsigned int size, void* res, const void* b, float f)
00128     {   MechanicalObjectCudaVec3f1_vPEqBF(size, res, b, f); }
00129     static void vAdd(unsigned int size, void* res, const void* a, const void* b)
00130     {   MechanicalObjectCudaVec3f1_vAdd(size, res, a, b); }
00131     static void vOp(unsigned int size, void* res, const void* a, const void* b, float f)
00132     {   MechanicalObjectCudaVec3f1_vOp(size, res, a, b, f); }
00133     static void vIntegrate(unsigned int size, const void* a, void* v, void* x, float f_v_v, float f_v_a, float f_x_x, float f_x_v)
00134     {   MechanicalObjectCudaVec3f1_vIntegrate(size, a, v, x, f_v_v, f_v_a, f_x_x, f_x_v); }
00135     static void vPEqBF2(unsigned int size, void* res1, const void* b1, float f1, void* res2, const void* b2, float f2)
00136     {   MechanicalObjectCudaVec3f1_vPEqBF2(size, res1, b1, f1, res2, b2, f2); }
00137     static void vPEq4BF2(unsigned int size, void* res1, const void* b11, float f11, const void* b12, float f12, const void* b13, float f13, const void* b14, float f14,
00138                                             void* res2, const void* b21, float f21, const void* b22, float f22, const void* b23, float f23, const void* b24, float f24)
00139     {   MechanicalObjectCudaVec3f1_vPEq4BF2(size, res1, b11, f11, b12, f12, b13, f13, b14, f14,
00140                                                  res2, b21, f21, b22, f22, b23, f23, b24, f24); }
00141     static void vOp2(unsigned int size, void* res1, const void* a1, const void* b1, float f1, void* res2, const void* a2, const void* b2, float f2)
00142     {   MechanicalObjectCudaVec3f1_vOp2(size, res1, a1, b1, f1, res2, a2, b2, f2); }
00143     static int vDotTmpSize(unsigned int size)
00144     {   return MechanicalObjectCudaVec3f1_vDotTmpSize(size); }
00145     static void vDot(unsigned int size, float* res, const void* a, const void* b, void* tmp, float* cputmp)
00146     {   MechanicalObjectCudaVec3f1_vDot(size, res, a, b, tmp, cputmp); }
00147 };
00148 
00149 
00150 } // namespace cuda
00151 
00152 } // namespace gpu
00153 
00154 namespace component
00155 {
00156 
00157 using namespace gpu::cuda;
00158 
00159 template<class TCoord, class TDeriv, class TReal>
00160 void MechanicalObjectInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::accumulateForce(Main* m)
00161 {
00162     if (!m->externalForces->empty())
00163     {
00164     Kernels::vAssign(m->externalForces->size(), m->f->deviceWrite(), m->externalForces->deviceRead());
00165     }
00166 }
00167 
00168 template<class TCoord, class TDeriv, class TReal>
00169 void MechanicalObjectInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::vAlloc(Main* m, VecId v)
00170 {
00171     if (v.type == VecId::V_COORD && v.index >= VecId::V_FIRST_DYNAMIC_INDEX)
00172     {
00173         VecCoord* vec = m->getVecCoord(v.index);
00174         vec->fastResize(m->vsize);
00175     }
00176     else if (v.type == VecId::V_DERIV && v.index >= VecId::V_FIRST_DYNAMIC_INDEX)
00177     {
00178         VecDeriv* vec = m->getVecDeriv(v.index);
00179         vec->fastResize(m->vsize);
00180     }
00181     else
00182     {
00183         std::cerr << "Invalid alloc operation ("<<v<<")\n";
00184         return;
00185     }
00186     //vOp(v); // clear vector
00187 }
00188 
00189 template<class TCoord, class TDeriv, class TReal>
00190 void MechanicalObjectInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::vOp(Main* m, VecId v, VecId a, VecId b, double f)
00191 {
00192     if(v.isNull())
00193     {
00194         // ERROR
00195         std::cerr << "Invalid vOp operation ("<<v<<','<<a<<','<<b<<','<<f<<")\n";
00196         return;
00197     }
00198     //std::cout << "> vOp operation ("<<v<<','<<a<<','<<b<<','<<f<<")\n";
00199     if (a.isNull())
00200     {
00201         if (b.isNull())
00202         {
00203             // v = 0
00204             if (v.type == VecId::V_COORD)
00205             {
00206                 VecCoord* vv = m->getVecCoord(v.index);
00207                 vv->fastResize(m->vsize);
00208                 Kernels::vClear(vv->size(), vv->deviceWrite());
00209             }
00210             else
00211             {
00212                 VecDeriv* vv = m->getVecDeriv(v.index);
00213                 vv->fastResize(m->vsize);
00214                 Kernels::vClear(vv->size(), vv->deviceWrite());
00215             }
00216         }
00217         else
00218         {
00219             if (b.type != v.type)
00220             {
00221                 // ERROR
00222                 std::cerr << "Invalid vOp operation ("<<v<<','<<a<<','<<b<<','<<f<<")\n";
00223                 return;
00224             }
00225             if (v == b)
00226             {
00227                 // v *= f
00228                 if (v.type == VecId::V_COORD)
00229                 {
00230                     VecCoord* vv = m->getVecCoord(v.index);
00231                     Kernels::vMEq(vv->size(), vv->deviceWrite(), (Real) f);
00232                 }
00233                 else
00234                 {
00235                     VecDeriv* vv = m->getVecDeriv(v.index);
00236                     Kernels::vMEq(vv->size(), vv->deviceWrite(), (Real) f);
00237                 }
00238             }
00239             else
00240             {
00241                 // v = b*f
00242                 if (v.type == VecId::V_COORD)
00243                 {
00244                     VecCoord* vv = m->getVecCoord(v.index);
00245                     VecCoord* vb = m->getVecCoord(b.index);
00246                     vv->fastResize(vb->size());
00247                     Kernels::vEqBF(vv->size(), vv->deviceWrite(), vb->deviceRead(), (Real) f);
00248                 }
00249                 else
00250                 {
00251                     VecDeriv* vv = m->getVecDeriv(v.index);
00252                     VecDeriv* vb = m->getVecDeriv(b.index);
00253                     vv->fastResize(vb->size());
00254                     Kernels::vEqBF(vv->size(), vv->deviceWrite(), vb->deviceRead(), (Real) f);
00255                 }
00256             }
00257         }
00258     }
00259     else
00260     {
00261         if (a.type != v.type)
00262         {
00263             // ERROR
00264             std::cerr << "Invalid vOp operation ("<<v<<','<<a<<','<<b<<','<<f<<")\n";
00265             return;
00266         }
00267         if (b.isNull())
00268         {
00269             // v = a
00270             if (v.type == VecId::V_COORD)
00271             {
00272                 VecCoord* vv = m->getVecCoord(v.index);
00273                 VecCoord* va = m->getVecCoord(a.index);
00274                 vv->fastResize(va->size());
00275                 Kernels::vAssign(vv->size(), vv->deviceWrite(), va->deviceRead());
00276             }
00277             else
00278             {
00279                 VecDeriv* vv = m->getVecDeriv(v.index);
00280                 VecDeriv* va = m->getVecDeriv(a.index);
00281                 vv->fastResize(va->size());
00282                 Kernels::vAssign(vv->size(), vv->deviceWrite(), va->deviceRead());
00283             }
00284         }
00285         else
00286         {
00287             if (v == a)
00288             {
00289                 if (f==1.0)
00290                 {
00291                     // v += b
00292                     if (v.type == VecId::V_COORD)
00293                     {
00294                         VecCoord* vv = m->getVecCoord(v.index);
00295                         if (b.type == VecId::V_COORD)
00296                         {
00297                             VecCoord* vb = m->getVecCoord(b.index);
00298                             vv->resize(vb->size());
00299                             Kernels::vPEq(vv->size(), vv->deviceWrite(), vb->deviceRead());
00300                         }
00301                         else
00302                         {
00303                             VecDeriv* vb = m->getVecDeriv(b.index);
00304                             vv->resize(vb->size());
00305                             Kernels::vPEq(vv->size(), vv->deviceWrite(), vb->deviceRead());
00306                         }
00307                     }
00308                     else if (b.type == VecId::V_DERIV)
00309                     {
00310                         VecDeriv* vv = m->getVecDeriv(v.index);
00311                         VecDeriv* vb = m->getVecDeriv(b.index);
00312                         vv->resize(vb->size());
00313                         Kernels::vPEq(vv->size(), vv->deviceWrite(), vb->deviceRead());
00314                     }
00315                     else
00316                     {
00317                         // ERROR
00318                         std::cerr << "Invalid vOp operation ("<<v<<','<<a<<','<<b<<','<<f<<")\n";
00319                         return;
00320                     }
00321                 }
00322                 else
00323                 {
00324                     // v += b*f
00325                     if (v.type == VecId::V_COORD)
00326                     {
00327                         VecCoord* vv = m->getVecCoord(v.index);
00328                         if (b.type == VecId::V_COORD)
00329                         {
00330                             VecCoord* vb = m->getVecCoord(b.index);
00331                             vv->resize(vb->size());
00332                             Kernels::vPEqBF(vv->size(), vv->deviceWrite(), vb->deviceRead(), (Real)f);
00333                         }
00334                         else
00335                         {
00336                             VecDeriv* vb = m->getVecDeriv(b.index);
00337                             vv->resize(vb->size());
00338                             Kernels::vPEqBF(vv->size(), vv->deviceWrite(), vb->deviceRead(), (Real)f);
00339                         }
00340                     }
00341                     else if (b.type == VecId::V_DERIV)
00342                     {
00343                         VecDeriv* vv = m->getVecDeriv(v.index);
00344                         VecDeriv* vb = m->getVecDeriv(b.index);
00345                         vv->resize(vb->size());
00346                         Kernels::vPEqBF(vv->size(), vv->deviceWrite(), vb->deviceRead(), (Real)f);
00347                     }
00348                     else
00349                     {
00350                         // ERROR
00351                         std::cerr << "Invalid vOp operation ("<<v<<','<<a<<','<<b<<','<<f<<")\n";
00352                         return;
00353                     }
00354                 }
00355             }
00356             else
00357             {
00358                 if (f==1.0)
00359                 {
00360                     // v = a+b
00361                     if (v.type == VecId::V_COORD)
00362                     {
00363                         VecCoord* vv = m->getVecCoord(v.index);
00364                         VecCoord* va = m->getVecCoord(a.index);
00365                         vv->fastResize(va->size());
00366                         if (b.type == VecId::V_COORD)
00367                         {
00368                             VecCoord* vb = m->getVecCoord(b.index);
00369                             Kernels::vAdd(vv->size(), vv->deviceWrite(), va->deviceRead(), vb->deviceRead());
00370                         }
00371                         else
00372                         {
00373                             VecDeriv* vb = m->getVecDeriv(b.index);
00374                             Kernels::vAdd(vv->size(), vv->deviceWrite(), va->deviceRead(), vb->deviceRead());
00375                         }
00376                     }
00377                     else if (b.type == VecId::V_DERIV)
00378                     {
00379                         VecDeriv* vv = m->getVecDeriv(v.index);
00380                         VecDeriv* va = m->getVecDeriv(a.index);
00381                         VecDeriv* vb = m->getVecDeriv(b.index);
00382                         vv->fastResize(va->size());
00383                         Kernels::vAdd(vv->size(), vv->deviceWrite(), va->deviceRead(), vb->deviceRead());
00384                     }
00385                     else
00386                     {
00387                         // ERROR
00388                         std::cerr << "Invalid vOp operation ("<<v<<','<<a<<','<<b<<','<<f<<")\n";
00389                         return;
00390                     }
00391                 }
00392                 else
00393                 {
00394                     // v = a+b*f
00395                     if (v.type == VecId::V_COORD)
00396                     {
00397                         VecCoord* vv = m->getVecCoord(v.index);
00398                         VecCoord* va = m->getVecCoord(a.index);
00399                         vv->fastResize(va->size());
00400                         if (b.type == VecId::V_COORD)
00401                         {
00402                             VecCoord* vb = m->getVecCoord(b.index);
00403                             Kernels::vOp(vv->size(), vv->deviceWrite(), va->deviceRead(), vb->deviceRead(), (Real)f);
00404                         }
00405                         else
00406                         {
00407                             VecDeriv* vb = m->getVecDeriv(b.index);
00408                             Kernels::vOp(vv->size(), vv->deviceWrite(), va->deviceRead(), vb->deviceRead(), (Real)f);
00409                         }
00410                     }
00411                     else if (b.type == VecId::V_DERIV)
00412                     {
00413                         VecDeriv* vv = m->getVecDeriv(v.index);
00414                         VecDeriv* va = m->getVecDeriv(a.index);
00415                         VecDeriv* vb = m->getVecDeriv(b.index);
00416                         vv->fastResize(va->size());
00417                         Kernels::vOp(vv->size(), vv->deviceWrite(), va->deviceRead(), vb->deviceRead(), (Real)f);
00418                     }
00419                     else
00420                     {
00421                         // ERROR
00422                         std::cerr << "Invalid vOp operation ("<<v<<','<<a<<','<<b<<','<<f<<")\n";
00423                         return;
00424                     }
00425                 }
00426             }
00427         }
00428     }
00429     //std::cout << "< vOp operation ("<<v<<','<<a<<','<<b<<','<<f<<")\n";
00430 }
00431 
00432 template<class TCoord, class TDeriv, class TReal>
00433 void MechanicalObjectInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::vMultiOp(Main* m, const VMultiOp& ops)
00434 {
00435     // optimize common integration case: v += a*dt, x += v*dt
00436     if (ops.size() == 2 && ops[0].second.size() == 2 && ops[0].first == ops[0].second[0].first && ops[0].first.type == VecId::V_DERIV && ops[0].second[1].first.type == VecId::V_DERIV
00437                     && ops[1].second.size() == 2 && ops[1].first == ops[1].second[0].first && ops[0].first == ops[1].second[1].first && ops[1].first.type == VecId::V_COORD)
00438     {
00439     VecDeriv* va = m->getVecDeriv(ops[0].second[1].first.index);
00440     VecDeriv* vv = m->getVecDeriv(ops[0].first.index);
00441     VecCoord* vx = m->getVecCoord(ops[1].first.index);
00442     const unsigned int n = vx->size();
00443     const double f_v_v = ops[0].second[0].second;
00444     const double f_v_a = ops[0].second[1].second;
00445     const double f_x_x = ops[1].second[0].second;
00446     const double f_x_v = ops[1].second[1].second;
00447     Kernels::vIntegrate(n, va->deviceRead(), vv->deviceWrite(), vx->deviceWrite(), (Real)f_v_v, (Real)f_v_a, (Real)f_x_x, (Real)f_x_v);
00448     }
00449     // optimize common CG step: x += a*p, q -= a*v
00450     else if (ops.size() == 2 && ops[0].second.size() == 2 && ops[0].first == ops[0].second[0].first && ops[0].second[0].second == 1.0 && ops[0].first.type == VecId::V_DERIV && ops[0].second[1].first.type == VecId::V_DERIV
00451                              && ops[1].second.size() == 2 && ops[1].first == ops[1].second[0].first && ops[1].second[0].second == 1.0 && ops[1].first.type == VecId::V_DERIV && ops[1].second[1].first.type == VecId::V_DERIV)
00452     {
00453         VecDeriv* vv1 = m->getVecDeriv(ops[0].second[1].first.index);
00454         VecDeriv* vres1 = m->getVecDeriv(ops[0].first.index);
00455         VecDeriv* vv2 = m->getVecDeriv(ops[1].second[1].first.index);
00456         VecDeriv* vres2 = m->getVecDeriv(ops[1].first.index);
00457         const unsigned int n = vres1->size();
00458         const double f1 = ops[0].second[1].second;
00459         const double f2 = ops[1].second[1].second;
00460         Kernels::vPEqBF2(n, vres1->deviceWrite(), vv1->deviceRead(), f1, vres2->deviceWrite(), vv2->deviceRead(), f2);
00461     }
00462     // optimize a pair of generic vOps
00463     else if (ops.size()==2 && ops[0].second.size()==2 && ops[0].second[0].second == 1.0 && ops[1].second.size()==2 && ops[1].second[0].second == 1.0)
00464     {
00465         const unsigned int n = m->getSize();
00466         Kernels::vOp2(n,
00467             (ops[0].first.type == VecId::V_COORD) ? m->getVecCoord(ops[0].first.index)->deviceWrite() : m->getVecDeriv(ops[0].first.index)->deviceWrite(),
00468             (ops[0].second[0].first.type == VecId::V_COORD) ? m->getVecCoord(ops[0].second[0].first.index)->deviceRead() : m->getVecDeriv(ops[0].second[0].first.index)->deviceRead(),
00469             (ops[0].second[1].first.type == VecId::V_COORD) ? m->getVecCoord(ops[0].second[1].first.index)->deviceRead() : m->getVecDeriv(ops[0].second[1].first.index)->deviceRead(),
00470             ops[0].second[1].second,
00471             (ops[1].first.type == VecId::V_COORD) ? m->getVecCoord(ops[1].first.index)->deviceWrite() : m->getVecDeriv(ops[1].first.index)->deviceWrite(),
00472             (ops[1].second[0].first.type == VecId::V_COORD) ? m->getVecCoord(ops[1].second[0].first.index)->deviceRead() : m->getVecDeriv(ops[1].second[0].first.index)->deviceRead(),
00473             (ops[1].second[1].first.type == VecId::V_COORD) ? m->getVecCoord(ops[1].second[1].first.index)->deviceRead() : m->getVecDeriv(ops[1].second[1].first.index)->deviceRead(),
00474             ops[1].second[1].second);
00475     }
00476     // optimize a pair of 4-way accumulations (such as at the end of RK4)
00477     else if (ops.size()==2 && ops[0].second.size()==5 && ops[0].second[0].first == ops[0].first && ops[0].second[0].second == 1.0 &&
00478                               ops[1].second.size()==5 && ops[1].second[0].first == ops[1].first && ops[1].second[0].second == 1.0)
00479     {
00480         const unsigned int n = m->getSize();
00481         Kernels::vPEq4BF2(n,
00482             (ops[0].first.type == VecId::V_COORD) ? m->getVecCoord(ops[0].first.index)->deviceWrite() : m->getVecDeriv(ops[0].first.index)->deviceWrite(),
00483             (ops[0].second[1].first.type == VecId::V_COORD) ? m->getVecCoord(ops[0].second[1].first.index)->deviceRead() : m->getVecDeriv(ops[0].second[1].first.index)->deviceRead(),
00484             ops[0].second[1].second,
00485             (ops[0].second[2].first.type == VecId::V_COORD) ? m->getVecCoord(ops[0].second[2].first.index)->deviceRead() : m->getVecDeriv(ops[0].second[2].first.index)->deviceRead(),
00486             ops[0].second[2].second,
00487             (ops[0].second[3].first.type == VecId::V_COORD) ? m->getVecCoord(ops[0].second[3].first.index)->deviceRead() : m->getVecDeriv(ops[0].second[3].first.index)->deviceRead(),
00488             ops[0].second[3].second,
00489             (ops[0].second[4].first.type == VecId::V_COORD) ? m->getVecCoord(ops[0].second[4].first.index)->deviceRead() : m->getVecDeriv(ops[0].second[4].first.index)->deviceRead(),
00490             ops[0].second[4].second,
00491             (ops[1].first.type == VecId::V_COORD) ? m->getVecCoord(ops[1].first.index)->deviceWrite() : m->getVecDeriv(ops[1].first.index)->deviceWrite(),
00492             (ops[1].second[1].first.type == VecId::V_COORD) ? m->getVecCoord(ops[1].second[1].first.index)->deviceRead() : m->getVecDeriv(ops[1].second[1].first.index)->deviceRead(),
00493             ops[1].second[1].second,
00494             (ops[1].second[2].first.type == VecId::V_COORD) ? m->getVecCoord(ops[1].second[2].first.index)->deviceRead() : m->getVecDeriv(ops[1].second[2].first.index)->deviceRead(),
00495             ops[1].second[2].second,
00496             (ops[1].second[3].first.type == VecId::V_COORD) ? m->getVecCoord(ops[1].second[3].first.index)->deviceRead() : m->getVecDeriv(ops[1].second[3].first.index)->deviceRead(),
00497             ops[1].second[3].second,
00498             (ops[1].second[4].first.type == VecId::V_COORD) ? m->getVecCoord(ops[1].second[4].first.index)->deviceRead() : m->getVecDeriv(ops[1].second[4].first.index)->deviceRead(),
00499             ops[1].second[4].second);
00500     }
00501     else // no optimization for now for other cases
00502     {
00503         std::cout << "CUDA: unoptimized vMultiOp:"<<std::endl;
00504         for (unsigned int i=0;i<ops.size();++i)
00505         {
00506             std::cout << ops[i].first << " =";
00507             if (ops[i].second.empty())
00508                 std::cout << "0";
00509             else
00510                 for (unsigned int j=0;j<ops[i].second.size();++j)
00511                 {
00512                     if (j) std::cout << " + ";
00513                     std::cout << ops[i].second[j].first << "*" << ops[i].second[j].second;
00514                 }
00515             std::cout << endl;
00516         }
00517         {
00518             using namespace sofa::core::componentmodel::behavior;
00519             m->BaseMechanicalState::vMultiOp(ops);
00520         }
00521     }
00522 }
00523 
00524 template<class TCoord, class TDeriv, class TReal>
00525 double MechanicalObjectInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::vDot(Main* m, VecId a, VecId b)
00526 {
00527     Real r = 0.0f;
00528     if (a.type == VecId::V_COORD && b.type == VecId::V_COORD)
00529     {
00530         VecCoord* va = m->getVecCoord(a.index);
00531         VecCoord* vb = m->getVecCoord(b.index);
00532         int tmpsize = Kernels::vDotTmpSize(va->size());
00533         if (tmpsize == 0)
00534         {
00535             Kernels::vDot(va->size(), &r, va->deviceRead(), vb->deviceRead(), NULL, NULL);
00536         }
00537         else
00538         {
00539             m->data.tmpdot.fastResize(tmpsize);
00540                         Kernels::vDot(va->size(), &r, va->deviceRead(), vb->deviceRead(), m->data.tmpdot.deviceWrite(), (Real*)(&(m->data.tmpdot.getCached(0))));
00541         }
00542     }
00543     else if (a.type == VecId::V_DERIV && b.type == VecId::V_DERIV)
00544     {
00545         VecDeriv* va = m->getVecDeriv(a.index);
00546         VecDeriv* vb = m->getVecDeriv(b.index);
00547         int tmpsize = Kernels::vDotTmpSize(va->size());
00548         if (tmpsize == 0)
00549         {
00550             Kernels::vDot(va->size(), &r, va->deviceRead(), vb->deviceRead(), NULL, NULL);
00551         }
00552         else
00553         {
00554             m->data.tmpdot.fastResize(tmpsize);
00555                         Kernels::vDot(va->size(), &r, va->deviceRead(), vb->deviceRead(), m->data.tmpdot.deviceWrite(), (Real*)(&(m->data.tmpdot.getCached(0))));
00556         }
00557 #ifndef NDEBUG
00558         // Check the result
00559         //Real r2 = 0.0f;
00560         //for (unsigned int i=0; i<va->size(); i++)
00561         //  r2 += (*va)[i] * (*vb)[i];
00562         //std::cout << "CUDA vDot: GPU="<<r<<"  CPU="<<r2<<" relative error="<<(fabsf(r2)>0.000001?fabsf(r-r2)/fabsf(r2):fabsf(r-r2))<<"\n";
00563 #endif
00564     }
00565     else
00566     {
00567         std::cerr << "Invalid dot operation ("<<a<<','<<b<<")\n";
00568     }
00569     return r;
00570 }
00571 
00572 template<class TCoord, class TDeriv, class TReal>
00573 void MechanicalObjectInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >::resetForce(Main* m)
00574 {
00575     VecDeriv& f= *m->getF();
00576     Kernels::vClear(f.size(), f.deviceWrite());
00577 }
00578 
00579 // I know using macros is bad design but this is the only way not to repeat the code for all CUDA types
00580 #define CudaMechanicalObject_ImplMethods(T) \
00581     template<> void MechanicalObject< T >::accumulateForce() \
00582     { data.accumulateForce(this); } \
00583     template<> void MechanicalObject< T >::vOp(VecId v, VecId a, VecId b, double f) \
00584     { data.vOp(this, v, a, b, f); } \
00585     template<> void MechanicalObject< T >::vMultiOp(const VMultiOp& ops) \
00586     { data.vMultiOp(this, ops); } \
00587     template<> double MechanicalObject< T >::vDot(VecId a, VecId b) \
00588     { return data.vDot(this, a, b); } \
00589     template<> void MechanicalObject< T >::resetForce() \
00590     { data.resetForce(this); }
00591 
00592 CudaMechanicalObject_ImplMethods(gpu::cuda::CudaVec3fTypes);
00593 CudaMechanicalObject_ImplMethods(gpu::cuda::CudaVec3f1Types);
00594 
00595 
00596 #undef CudaMechanicalObject_ImplMethods
00597 
00598 } // namespace component
00599 
00600 } // namespace sofa
00601 
00602 #endif

Generated on Sun Nov 23 04:00:03 2008 for Sofa by  doxygen 1.5.7.1