Parallel for

Parallel seismic simulation that demonstrates use of parallel_for.

 

SeismicSimulation.h
==============================================================================
Copyright 2005-2006 Intel Corporation. All Rights Reserved.
==============================================================================

typedef unsigned char ColorLevel; 
struct ColorType { 
ColorLevel blue; 
ColorLevel green; 
ColorLevel red; 
ColorLevel pad; 
}; 
const size_t MAX_WIDTH = 1024; 
const size_t MAX_HEIGHT = 1024; 
extern int UniverseWidth; 
extern int UniverseHeight; 
extern ColorType TheImage[MAX_HEIGHT][MAX_WIDTH]; 
extern void SerialUpdateUniverse(); 
extern void ParallelUpdateUniverse(); 
extern void InitializeUniverse(); 
extern void MouseDown( int, int ); 

 

SeismicSimulation.cpp
==============================================================================
Copyright 2005-2006 Intel Corporation. All Rights Reserved.
==============================================================================

// warning C4068: unknown pragma 

static int GrainSize = 32; 
ColorType TheImage[MAX_HEIGHT][MAX_WIDTH]; 
int UniverseHeight=512; 
int UniverseWidth=1024; 
static float V[MAX_HEIGHT][MAX_WIDTH]; 
static float S[MAX_HEIGHT][MAX_WIDTH]; 
static float T[MAX_HEIGHT][MAX_WIDTH]; 
static float M[MAX_HEIGHT]; 
enum MaterialType { 
WATER=0, 
SANDSTONE=1, 
SHALE=2 
}; 
//! Values are MaterialType, cast to an unsigned char to save space. 
static unsigned char Material[MAX_HEIGHT]; 
static const ColorType MaterialColor[4] = { 
{96,0,0,0}, // WATER 
{0,48,48,0}, // SANDSTONE 
{32,32,23,0} // SHALE 
}; 
static const int DamperSize = 32; 
static float Damper[DamperSize]; 
static const int ColorMapSize = 1024; 
static ColorType ColorMap[4][ColorMapSize]; 
static int PulseTime = 100; 
static int PulseCounter; 
static int PulseX = UniverseWidth/3; 
static int PulseY = UniverseHeight/4; 
static void UpdatePulse() { 
if( PulseCounter>0 ) { 
float t = (PulseCounter-PulseTime/2)*0.05f; 
V[PulseY][PulseX] += 64*sqrt(M[PulseY])*exp(-t*t); 
--PulseCounter; 
} 
} 
static void SerialUpdateStress() { 
for( int i=1; i<UniverseHeight-1; ++i ) { 
ColorType* c = ColorMap[Material[i]]; 

for( int j=1; j<UniverseWidth-1; ++j ) { 
S[i][j] += (V[i][j+1]-V[i][j]); 
T[i][j] += (V[i+1][j]-V[i][j]); 
int index = (int)(V[i][j]*(ColorMapSize/2)) + ColorMapSize/2; 
if( index<0 ) index = 0; 
if( index>=ColorMapSize ) index = ColorMapSize-1; 
TheImage[i][j] = c[index]; 
} 
} 
} 
struct UpdateStressBody { 
void operator()( const tbb::blocked_range<int>& range ) const { 
int i_end = range.end(); 
for( int i=range.begin(); i!=i_end; ++i ) { 
ColorType* c = ColorMap[Material[i]]; 

for( int j=1; j<UniverseWidth-1; ++j ) { 
S[i][j] += (V[i][j+1]-V[i][j]); 
T[i][j] += (V[i+1][j]-V[i][j]); 
int index = (int)(V[i][j]*(ColorMapSize/2)) + ColorMapSize/2; 
if( index<0 ) index = 0; 
if( index>=ColorMapSize ) index = ColorMapSize-1; 
TheImage[i][j] = c[index]; 
} 
} 
} 
}; 
static void ParallelUpdateStress() { 
tbb::parallel_for( tbb::blocked_range<int>( 1, UniverseHeight-1, GrainSize ), UpdateStressBody() ); 
} 
static void SerialUpdateVelocity() { 
for( int i=1; i<UniverseHeight-1; ++i ) 

for( int j=1; j<UniverseWidth -1; ++j ) { 
V[i][j] += (S[i][j] - S[i][j-1] + T[i][j] - T[i-1][j])*M[i]; 
} 
} 
struct UpdateVelocityBody { 
void operator()( const tbb::blocked_range<int>& range ) const { 
int i_end = range.end(); 
for( int i=range.begin(); i!=i_end; ++i ) { 

for( int j=1; j<UniverseWidth-1; ++j ) { 
V[i][j] += (S[i][j] - S[i][j-1] + T[i][j] - T[i-1][j])*M[i]; 
} 
} 
} 
}; 
static void ParallelUpdateVelocity() { 
tbb::parallel_for( tbb::blocked_range<int>( 1, UniverseHeight-1, GrainSize ), UpdateVelocityBody() ); 
} 
static void DrainEnergyFromBorders() { 

for( int k=1; k<=DamperSize-1; ++k ) { 
float d = Damper[k]; 
for( int j=1; j<UniverseWidth-1; ++j ) { 
V[k][j] *= d; 
V[UniverseHeight-k][j] *= d; 
} 
for( int i=1; i<UniverseHeight-1; ++i ) { 
V[i][k] *= d; 
V[i][UniverseWidth-k] *= d; 
} 
} 
} 
void SerialUpdateUniverse() { 
UpdatePulse(); 
SerialUpdateStress(); 
SerialUpdateVelocity(); 
DrainEnergyFromBorders(); 
} 
void ParallelUpdateUniverse() { 
UpdatePulse(); 
ParallelUpdateStress(); 
ParallelUpdateVelocity(); 
DrainEnergyFromBorders(); 
} 
void InitializeUniverse() { 
PulseCounter = PulseTime; 
for( int i=1; i<UniverseHeight-1; ++i ) { 
float t = (float)i/UniverseHeight; 
MaterialType m = SANDSTONE; 
M[i] = 1.0/8; 
if( t<0.3f ) { 
m = WATER; 
M[i] = 1.0/32; 
} else if( 0.5<=t && t<=0.7 ) { 
m = SHALE; 
M[i] = 1.0/2; 
} 
Material[i] = m; 
} 
float scale = 2.0f/ColorMapSize; 
for( int k=0; k<4; ++k ) { 
for( int i=0; i<ColorMapSize; ++i ) { 
ColorType c; 
float t = (i-ColorMapSize/2)*scale; 
float r = t>0 ? t : 0; 
float b = t<0 ? -t : 0; 
float g = 0.5f*fabs(t); 
c = MaterialColor[k]; 
c.red = ColorLevel(r*(255-c.red)+c.red); 
c.green = ColorLevel(g*(255-c.green)+c.green); 
c.blue = ColorLevel(b*(255-c.blue)+c.blue); 
ColorMap[k][i] = c; 
} 
} 
float d = 1.0; 
for( int k=0; k<DamperSize; ++k ) { 
d *= 1-1.0f/(DamperSize*DamperSize); 
Damper[DamperSize-1-k] = d; 
} 
} 
void MouseDown( int x, int y ) { 
if( PulseCounter==0 ) { 
PulseCounter = PulseTime; 
PulseX = x; 
PulseY = y; 
} 
} 

 

Please also note the three attached files below. They are also needed for a complete program.

 


For more complete information about compiler optimizations, see our Optimization Notice.
AttachmentSize
File commandlineinterface.cpp2.82 KB
File common.h1.38 KB
File graphicaluserinterface.cpp8.73 KB