Parallel for

Submit New Article

March 9, 2009 1:00 AM PDT


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.