Equalizer
1.2.1
|
00001 00002 /* 00003 * Copyright (c) 2009, Philippe Robert <philippe.robert@gmail.com> 00004 * 2010-2011, Stefan Eilemann <eile@eyescale.ch> 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions are met: 00008 * 00009 * - Redistributions of source code must retain the above copyright notice, this 00010 * list of conditions and the following disclaimer. 00011 * - Redistributions in binary form must reproduce the above copyright notice, 00012 * this list of conditions and the following disclaimer in the documentation 00013 * and/or other materials provided with the distribution. 00014 * - Neither the name of Eyescale Software GmbH nor the names of its 00015 * contributors may be used to endorse or promote products derived from this 00016 * software without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00028 * POSSIBILITY OF SUCH DAMAGE. 00029 */ 00030 00031 #include "frameData.h" 00032 #include "nbody.h" 00033 00034 #include <cuda.h> 00035 00036 #if CUDART_VERSION >= 2020 00037 # define ENABLE_HOSTALLOC 00038 #endif 00039 00040 namespace eqNbody 00041 { 00042 FrameData::FrameData() : _statistics( true ) , _numDataProxies(0), _hPos(0) 00043 , _hVel(0), _hCol(0) 00044 { 00045 _numBodies = 0; 00046 _deltaTime = 0.0f; 00047 _clusterScale = 0.0f; 00048 _velocityScale = 0.0f; 00049 _newParameters = false; 00050 } 00051 00052 FrameData::~FrameData() 00053 { 00054 _numDataProxies = 0; 00055 } 00056 00057 void FrameData::serialize( co::DataOStream& os, const uint64_t dirtyBits ) 00058 { 00059 co::Serializable::serialize( os, dirtyBits ); 00060 00061 if( dirtyBits & DIRTY_DATA ) { 00062 if(_hPos && _hVel && _hCol) { 00063 os.write(_hPos, sizeof(float)*_numBodies*4); 00064 os.write(_hVel, sizeof(float)*_numBodies*4); 00065 os.write(_hCol, sizeof(float)*_numBodies*4); 00066 } 00067 } 00068 00069 if( dirtyBits & DIRTY_FLAGS ) 00070 os << _statistics << _numBodies << _clusterScale << _velocityScale 00071 << _deltaTime << _newParameters; 00072 00073 if( dirtyBits & DIRTY_PROXYDATA ) 00074 { 00075 os << _numDataProxies; 00076 os.write( _dataProxyID, sizeof(co::ObjectVersion) * MAX_NGPUS ); 00077 os.write(&_dataRanges[0], sizeof(float) * MAX_NGPUS); 00078 } 00079 } 00080 00081 void FrameData::deserialize( co::DataIStream& is, 00082 const uint64_t dirtyBits ) 00083 { 00084 co::Serializable::deserialize( is, dirtyBits ); 00085 00086 if( dirtyBits & DIRTY_DATA ) { 00087 if(_hPos && _hVel && _hCol) { 00088 is.read(_hPos, sizeof(float)*_numBodies*4); 00089 is.read(_hVel, sizeof(float)*_numBodies*4); 00090 is.read(_hCol, sizeof(float)*_numBodies*4); 00091 } 00092 } 00093 00094 if( dirtyBits & DIRTY_FLAGS ) 00095 is >> _statistics >> _numBodies >> _clusterScale >> _velocityScale 00096 >> _deltaTime >> _newParameters; 00097 00098 if( dirtyBits & DIRTY_PROXYDATA ) 00099 { 00100 is >> _numDataProxies; 00101 is.read( _dataProxyID, sizeof( co::ObjectVersion ) * MAX_NGPUS ); 00102 is.read(&_dataRanges[0], sizeof(float) * MAX_NGPUS); 00103 } 00104 } 00105 00106 void FrameData::addProxyID( const eq::uint128_t& pid, const float *range ) 00107 { 00108 EQASSERT(_numDataProxies < MAX_NGPUS); 00109 00110 _dataProxyID[_numDataProxies].identifier = pid; 00111 _dataProxyID[_numDataProxies].version = co::VERSION_NONE; 00112 00113 _dataRanges[_numDataProxies++] = (range[1] - range[0]); 00114 setDirty( DIRTY_PROXYDATA ); 00115 } 00116 00117 void FrameData::updateProxyID( const eq::uint128_t& pid, 00118 const eq::uint128_t& version, 00119 const float *range ) 00120 { 00121 // TODO: Better use a hash here! 00122 for(unsigned int i=0; i< _numDataProxies; i++) 00123 { 00124 if( pid == _dataProxyID[i].identifier ) 00125 { 00126 _dataProxyID[i].version = version; 00127 _dataRanges[i] = (range[1] - range[0]); 00128 break; 00129 } 00130 } 00131 setDirty( DIRTY_PROXYDATA ); 00132 } 00133 00134 eq::uint128_t FrameData::commit() 00135 { 00136 const eq::uint128_t v = co::Serializable::commit(); 00137 for( unsigned int i = 0; i< _numDataProxies; ++i ) 00138 _dataRanges[i] = 0.0f; 00139 00140 return v; 00141 } 00142 00143 bool FrameData::isReady() 00144 { 00145 float length = 0.0f; 00146 00147 for(unsigned int i=0; i<_numDataProxies; i++) { 00148 length += _dataRanges[i]; 00149 } 00150 00151 // Return true if range [0 1] is covered, otherwise false 00152 return (length == 1.0f) ? true : false; 00153 } 00154 00155 eq::uint128_t FrameData::getVersionForProxyID( const eq::uint128_t& pid ) const 00156 { 00157 // TODO: Better use a hash here! 00158 for( unsigned int i=0; i< _numDataProxies; ++i ) 00159 { 00160 if( pid == getProxyID( i )) 00161 return getProxyVersion( i ); 00162 } 00163 00164 return 0; 00165 } 00166 00167 void FrameData::toggleStatistics() 00168 { 00169 _statistics = !_statistics; 00170 setDirty( DIRTY_FLAGS ); 00171 } 00172 00173 void FrameData::init(const unsigned int numBodies) 00174 { 00175 _numBodies = numBodies; 00176 00177 setDirty( DIRTY_FLAGS ); 00178 } 00179 00180 void FrameData::initHostData() 00181 { 00182 #ifdef ENABLE_HOSTALLOC 00183 allocateHostArrays(&_hPos, &_hVel, &_hCol, _numBodies*4*sizeof(float)); 00184 #else 00185 _hPos = new float[_numBodies*4]; 00186 _hVel = new float[_numBodies*4]; 00187 _hCol = new float[_numBodies*4]; 00188 #endif 00189 00190 memset(_hPos, 0, _numBodies*4*sizeof(float)); 00191 memset(_hVel, 0, _numBodies*4*sizeof(float)); 00192 memset(_hCol, 0, _numBodies*4*sizeof(float)); 00193 00194 setDirty( DIRTY_DATA ); 00195 } 00196 00197 void FrameData::exit() 00198 { 00199 _numDataProxies = 0; 00200 _numBodies = 0; 00201 00202 #ifdef ENABLE_HOSTALLOC 00203 deleteHostArrays(_hPos, _hVel, _hCol); 00204 #else 00205 delete [] _hPos; 00206 delete [] _hVel; 00207 delete [] _hCol; 00208 #endif 00209 } 00210 00211 void FrameData::updateParameters(NBodyConfig config, float clusterScale, float velocityScale, float ts) 00212 { 00213 _clusterScale = clusterScale; 00214 _velocityScale = velocityScale; 00215 _deltaTime = ts; 00216 _newParameters = true; 00217 00218 _randomizeData(config); 00219 00220 setDirty( DIRTY_DATA ); 00221 setDirty( DIRTY_FLAGS ); 00222 } 00223 00224 void FrameData::_randomizeData(NBodyConfig config) 00225 { 00226 switch(config) 00227 { 00228 default: 00229 case NBODY_CONFIG_RANDOM: 00230 { 00231 float scale = _clusterScale * std::max(1.0f, _numBodies / (1024.f)); 00232 float vscale = _velocityScale * scale; 00233 00234 int p = 0, v = 0; 00235 unsigned int i = 0; 00236 while (i < _numBodies) 00237 { 00238 eq::Vector3f point; 00239 //const int scale = 16; 00240 point.x() = rand() / (float) RAND_MAX * 2 - 1; 00241 point.y() = rand() / (float) RAND_MAX * 2 - 1; 00242 point.z() = rand() / (float) RAND_MAX * 2 - 1; 00243 float lenSqr = point.squared_length(); 00244 if (lenSqr > 1) 00245 continue; 00246 eq::Vector3f velocity; 00247 velocity.x() = rand() / (float) RAND_MAX * 2 - 1; 00248 velocity.y() = rand() / (float) RAND_MAX * 2 - 1; 00249 velocity.z() = rand() / (float) RAND_MAX * 2 - 1; 00250 lenSqr = velocity.squared_length(); 00251 if (lenSqr > 1) 00252 continue; 00253 00254 _hPos[p++] = point.x() * scale; // pos.x 00255 _hPos[p++] = point.y() * scale; // pos.y 00256 _hPos[p++] = point.z() * scale; // pos.z 00257 _hPos[p++] = 1.0f; // mass 00258 00259 _hVel[v++] = velocity.x() * vscale; // pos.x 00260 _hVel[v++] = velocity.y() * vscale; // pos.x 00261 _hVel[v++] = velocity.z() * vscale; // pos.x 00262 _hVel[v++] = 1.0f; // inverse mass 00263 00264 i++; 00265 } 00266 } 00267 break; 00268 case NBODY_CONFIG_SHELL: 00269 { 00270 float scale = _clusterScale; 00271 float vscale = scale * _velocityScale; 00272 float inner = 2.5f * scale; 00273 float outer = 4.0f * scale; 00274 00275 int p = 0, v=0; 00276 unsigned int i = 0; 00277 while (i < _numBodies)//for(int i=0; i < numBodies; i++) 00278 { 00279 float x, y, z; 00280 x = rand() / (float) RAND_MAX * 2 - 1; 00281 y = rand() / (float) RAND_MAX * 2 - 1; 00282 z = rand() / (float) RAND_MAX * 2 - 1; 00283 00284 eq::Vector3f point( x, y, z ); 00285 float len = point.normalize(); 00286 if (len > 1) 00287 continue; 00288 00289 _hPos[p++] = point.x() * (inner + (outer - inner) * rand() / (float) RAND_MAX); 00290 _hPos[p++] = point.y() * (inner + (outer - inner) * rand() / (float) RAND_MAX); 00291 _hPos[p++] = point.z() * (inner + (outer - inner) * rand() / (float) RAND_MAX); 00292 _hPos[p++] = 1.0f; 00293 00294 x = 0.0f; // * (rand() / (float) RAND_MAX * 2 - 1); 00295 y = 0.0f; // * (rand() / (float) RAND_MAX * 2 - 1); 00296 z = 1.0f; // * (rand() / (float) RAND_MAX * 2 - 1); 00297 eq::Vector3f axis( x, y, z ); 00298 axis.normalize(); 00299 00300 if (1 - point.dot(axis) < 1e-6) 00301 { 00302 axis.x() = point.y(); 00303 axis.y() = point.x(); 00304 axis.normalize(); 00305 } 00306 //if (point.y < 0) axis = scalevec(axis, -1); 00307 eq::Vector3f vv( _hPos[4*i], _hPos[4*i+1], _hPos[4*i+2] ); 00308 vv = vv.cross( axis ); 00309 _hVel[v++] = vv.x() * vscale; 00310 _hVel[v++] = vv.y() * vscale; 00311 _hVel[v++] = vv.z() * vscale; 00312 _hVel[v++] = 1.0f; 00313 00314 i++; 00315 } 00316 } 00317 break; 00318 case NBODY_CONFIG_EXPAND: 00319 { 00320 float scale = _clusterScale * std::max(1.0f, _numBodies / (1024.f)); 00321 float vscale = scale * _velocityScale; 00322 00323 int p = 0, v = 0; 00324 for(unsigned int i=0; i < _numBodies;) 00325 { 00326 eq::Vector3f point; 00327 00328 point.x() = rand() / (float) RAND_MAX * 2 - 1; 00329 point.y() = rand() / (float) RAND_MAX * 2 - 1; 00330 point.z() = rand() / (float) RAND_MAX * 2 - 1; 00331 00332 float lenSqr = point.squared_length(); 00333 if (lenSqr > 1) 00334 continue; 00335 00336 _hPos[p++] = point.x() * scale; // pos.x 00337 _hPos[p++] = point.y() * scale; // pos.y 00338 _hPos[p++] = point.z() * scale; // pos.z 00339 _hPos[p++] = 1.0f; // mass 00340 00341 _hVel[v++] = point.x() * vscale; // pos.x 00342 _hVel[v++] = point.y() * vscale; // pos.x 00343 _hVel[v++] = point.z() * vscale; // pos.x 00344 _hVel[v++] = 1.0f; // inverse mass 00345 00346 i++; 00347 } 00348 } 00349 break; 00350 } 00351 00352 if (_hCol) 00353 { 00354 int v = 0; 00355 for(unsigned int i=0; i < _numBodies; i++) 00356 { 00357 _hCol[v++] = rand() / (float) RAND_MAX; 00358 _hCol[v++] = rand() / (float) RAND_MAX; 00359 _hCol[v++] = rand() / (float) RAND_MAX; 00360 _hCol[v++] = 1.0f; 00361 } 00362 } 00363 } 00364 } 00365