int main() { Vectors3DSOA points, dirs, intermediatepoints, intermediatedirs; StructOfCoord rpoints, rintermediatepoints, rdirs, rintermediatedirs; int np=1024; points.alloc(np); dirs.alloc(np); intermediatepoints.alloc(np); intermediatedirs.alloc(np); rpoints.alloc(np); rdirs.alloc(np); rintermediatepoints.alloc(np); rintermediatedirs.alloc(np); double *distances = (double *) _mm_malloc(np*sizeof(double), ALIGNMENT_BOUNDARY); double *distances2 = (double *) _mm_malloc(np*sizeof(double), ALIGNMENT_BOUNDARY); double *steps = (double *) _mm_malloc(np*sizeof(double), ALIGNMENT_BOUNDARY); for(auto i=0;i<np;++i) steps[i]=1E30; std::vector<Vector3D> conventionalpoints(np); std::vector<Vector3D> conventionaldirs(np); Vector3D * conventionalpoints2 = (Vector3D *) new Vector3D[np]; Vector3D * conventionaldirs2 = (Vector3D *) new Vector3D[np]; StopWatch timer; // generate benchmark cases for( int r=0; r< EulerAngles.size(); ++r ) // rotation cases for( int t=0; t<TransCases.size(); ++t ) // translation cases { TransformationMatrix const * identity = new TransformationMatrix(0,0,0,0,0,0); PhysicalVolume * world = GeoManager::MakePlacedBox( new BoxParameters(100,100,100), identity ); TransformationMatrix * tm = new TransformationMatrix(TransCases[t][0], TransCases[t][1], TransCases[t][2], EulerAngles[r][0], EulerAngles[r][1], EulerAngles[r][2]); // these dispatch to specialized matrices TransformationMatrix const * sm = TransformationMatrix::createSpecializedMatrix( TransCases[t][0], TransCases[t][1], TransCases[t][2], EulerAngles[r][0], EulerAngles[r][1], EulerAngles[r][2] ); PhysicalVolume * daughter = GeoManager::MakePlacedBox( new BoxParameters(10,15,20), tm ); world->AddDaughter(daughter); world->fillWithRandomPoints(points,np); world->fillWithBiasedDirections(points, dirs, np, 1./10); points.toStructureOfVector3D( conventionalpoints ); dirs.toStructureOfVector3D( conventionaldirs ); points.toStructureOfVector3D( conventionalpoints2 ); dirs.toStructureOfVector3D( conventionaldirs2 ); // time performance for this placement ( we should probably include some random physical steps ) timer.Start(); for(int reps=0;reps<1000;reps++) { daughter->DistanceToIn(points,dirs,steps,distances); } timer.Stop(); double t0 = timer.getDeltaSecs(); // std::cerr << tm->GetTranslationIdType() << " " << tm->getNumberOfZeroEntries() << " " << timer.getDeltaSecs() << std::endl; timer.Start(); for(int reps=0;reps<1000;reps++) { daughter->DistanceToInIL(points,dirs,steps,distances); } timer.Stop(); double til = timer.getDeltaSecs(); timer.Start(); for(int reps=0;reps<1000;reps++) { daughter->DistanceToInIL( conventionalpoints2, conventionaldirs2, steps, distances, np ); } timer.Stop(); double til2 = timer.getDeltaSecs(); // compare with case that uses external unspecialized transformation PhysicalVolume * unplaceddaughter = GeoManager::MakePlacedBox(new BoxParameters(10,15,20), identity); timer.Start(); for(int reps=0;reps<1000;reps++) { if(! tm->isIdentity() ) { tm->MasterToLocal(points, intermediatepoints ); tm->MasterToLocalVec( dirs, intermediatedirs ); unplaceddaughter->DistanceToIn( intermediatepoints, intermediatedirs, steps, distances2); } else { unplaceddaughter->DistanceToIn( points, dirs, steps, distances2); } } timer.Stop(); double t1 = timer.getDeltaSecs(); // compare with external specialized transformation ( sm ) sm->print(); timer.Start(); for(int reps=0;reps<1000;reps++) { sm->MasterToLocal(points, intermediatepoints ); sm->MasterToLocalVec( dirs, intermediatedirs ); unplaceddaughter->DistanceToIn( intermediatepoints, intermediatedirs, steps, distances2); } timer.Stop(); double t2 = timer.getDeltaSecs(); std::cerr << "VECTOR " << tm->isTranslation() << " " << tm->isRotation() << "("<<tm->getNumberOfZeroEntries()<<")" << " " << t0 << " " << t1 << " " << t2 << " " << til << " " << til2 << std::endl; cmpresults( distances, distances2, np ); // now we do the scalar interface: first of all placed version timer.Start(); for(int reps=0;reps<1000;reps++) { for(auto j=0;j<np;++j) { distances[j]=daughter->DistanceToIn( conventionalpoints[j], conventionaldirs[j], steps[j]); } } timer.Stop(); double t3 = timer.getDeltaSecs(); // now unplaced version timer.Start(); for(int reps=0;reps<1000;reps++) { for(auto j=0;j<np;++j) { Vector3D localp, localdir; tm->MasterToLocal(conventionalpoints[j], localp); tm->MasterToLocalVec(conventionaldirs[j], localdir); distances2[j]=unplaceddaughter->DistanceToIn( localp, localdir, steps[j]); } } timer.Stop(); double t4 = timer.getDeltaSecs(); // now unplaced version timer.Start(); for(int reps=0;reps<1000;reps++) { for(auto j=0;j<np;++j) { Vector3D localp, localdir; sm->MasterToLocal(conventionalpoints[j], localp); sm->MasterToLocalVec(conventionaldirs[j], localdir); distances2[j]=unplaceddaughter->DistanceToIn( localp, localdir, steps[j]); } } timer.Stop(); double t5 = timer.getDeltaSecs(); // now unplaced version but inlined matrices timer.Start(); for(int reps=0;reps<1000;reps++) { for(auto j=0;j<np;++j) { Vector3D localp, localdir; // this inlines I think tm->MasterToLocal<-1,-1>(conventionalpoints[j], localp); tm->MasterToLocalVec<-1>(conventionaldirs[j], localdir); distances2[j]=unplaceddaughter->DistanceToIn( localp, localdir, 1E30); } } timer.Stop(); double t6 = timer.getDeltaSecs(); std::cerr << "SCALAR " << tm->isTranslation() << " " << tm->isRotation() << "("<<tm->getNumberOfZeroEntries()<<")" << " " << t3 << " " << t4 << " " << t5 << " " << t6 << std::endl; TGeoMatrix * rootmatrix= new TGeoCombiTrans(TransCases[t][0], TransCases[t][1], TransCases[t][2], new TGeoRotation("rot1",EulerAngles[r][0], EulerAngles[r][1], EulerAngles[r][2])); TGeoManager *geom = new TGeoManager("",""); TGeoVolume * vol = geom->MakeBox("abox",0,10,15,20); TGeoShape * rootbox=vol->GetShape(); // now the scalar version from ROOTGeantV timer.Start(); for(int reps=0;reps<1000;reps++) { for(auto j=0;j<np;++j) { Vector3D localp, localdir; // this inlines I think rootmatrix->MasterToLocal( &conventionalpoints[j].x, &localp.x ); rootmatrix->MasterToLocalVect( &conventionaldirs[j].x, &localdir.x ); distances[j]=rootbox->DistFromOutside( &localp.x, &localdir.x, 3,1e30, 0); } } timer.Stop(); double t7 = timer.getDeltaSecs(); // now the VECTOR version from ROOT // now the scalar version from ROOTGeantV timer.Start(); for(int reps=0;reps<1000;reps++) { rootmatrix->MasterToLocalCombined_v( reinterpret_cast<StructOfCoord const &>(points), reinterpret_cast<StructOfCoord &>(intermediatepoints), reinterpret_cast<StructOfCoord const &>(dirs), reinterpret_cast<StructOfCoord &>(intermediatedirs), np ); rootbox->DistFromOutsideSOA_v( reinterpret_cast<StructOfCoord const &>(intermediatepoints), reinterpret_cast<StructOfCoord const &>(intermediatedirs), 3, steps, 0, distances2, np); } timer.Stop(); double t8 = timer.getDeltaSecs(); std::cerr << "RSCAL " << tm->isTranslation() << " " << tm->isRotation() << "("<<tm->getNumberOfZeroEntries()<<")" << " " << t7 << std::endl; std::cerr << "RVEC " << tm->isTranslation() << " " << tm->isRotation() << "("<<tm->getNumberOfZeroEntries()<<")" << " " << t8 << std::endl; cmpresults( distances, distances2, np ); delete tm; delete sm; } _mm_free(distances); return 1; }