瀏覽代碼

test: proper multithreading in the Mandelbrot tutorial.

legacy
Sam Hocevar sam 14 年之前
父節點
當前提交
608f52eefb
共有 1 個文件被更改,包括 42 次插入33 次删除
  1. +42
    -33
      test/tutorial/tut03.cpp

+ 42
- 33
test/tutorial/tut03.cpp 查看文件

@@ -104,9 +104,9 @@ public:
{ {
double f = (double)i / PALETTE_STEP; double f = (double)i / PALETTE_STEP;


double r = 0.5 * sin(f * 0.27 - 2.5) + 0.5;
double g = 0.5 * sin(f * 0.13 + 1.1) + 0.5;
double b = 0.5 * sin(f * 0.21 + 0.4) + 0.5;
double r = 0.5 * sin(f * 0.27 + 2.0) + 0.5;
double g = 0.5 * sin(f * 0.17 - 1.8) + 0.5;
double b = 0.5 * sin(f * 0.21 - 2.6) + 0.5;


if (f < 7.0) if (f < 7.0)
{ {
@@ -146,10 +146,20 @@ public:
bbox[0] = position; bbox[0] = position;
bbox[1] = ivec3(m_window_size, 0); bbox[1] = ivec3(m_window_size, 0);
Input::TrackMouse(this); Input::TrackMouse(this);

/* Spawn worker threads and wait for their readiness. */
for (int i = 0; i < MAX_THREADS; i++)
m_threads[i] = new Thread(DoWorkHelper, this);
for (int i = 0; i < MAX_THREADS; i++)
m_spawnqueue.Pop();
} }


~Fractal() ~Fractal()
{ {
/* Signal worker threads for completion. */
for (int i = 0; i < MAX_THREADS; i++)
m_jobqueue.Push(-1);

Input::UntrackMouse(this); Input::UntrackMouse(this);
#if !defined __native_client__ #if !defined __native_client__
Ticker::Unref(m_centertext); Ticker::Unref(m_centertext);
@@ -307,49 +317,39 @@ public:
{ {
m_dirty[m_frame]--; m_dirty[m_frame]--;


/* FIXME: this is the ugliest, most pathetic excuse for a
* threading system that I have seen in a while. */
DoWorkHelper helpers[m_slices];
for (int slice = 0; slice < m_slices; slice++)
{
helpers[slice].fractal = this;
helpers[slice].slice = slice;
// helpers[slice].thread = new Thread(DoWorkHelper::Help,
// &helpers[slice]);
DoWork(slice);
}
for (int slice = 0; slice < m_slices; slice++)
{
// delete helpers[slice].thread;
}
for (int i = 0; i < m_size.y; i += MAX_LINES * 2)
m_jobqueue.Push(i);
} }
} }


struct DoWorkHelper
static void *DoWorkHelper(void *data)
{ {
Fractal *fractal;
Thread *thread;
int slice;

static void *Help(void *data)
Fractal *that = (Fractal *)data;
that->m_spawnqueue.Push(0);
for ( ; ; )
{ {
DoWorkHelper *helper = (DoWorkHelper *)data;
helper->fractal->DoWork(helper->slice);
return NULL;
int line = that->m_jobqueue.Pop();
if (line == -1)
break;
that->DoWork(line);
that->m_donequeue.Push(0);
} }
return NULL;
}; };


void DoWork(int slice)
void DoWork(int line)
{ {
double const maxsqlen = 1024; double const maxsqlen = 1024;
double const k1 = 1.0 / (1 << 10) / log2(maxsqlen); double const k1 = 1.0 / (1 << 10) / log2(maxsqlen);


int jmin = m_size.y * slice / m_slices;
int jmax = m_size.y * (slice + 1) / m_slices;
int jmin = ((m_frame + 1) % 4) / 2 + line;
int jmax = jmin + MAX_LINES * 2;
if (jmax > m_size.y)
jmax = m_size.y;
u8vec4 *m_pixelstart = m_pixels u8vec4 *m_pixelstart = m_pixels
+ m_size.x * (m_size.y / 4 * m_frame + jmin / 4);
+ m_size.x * (m_size.y / 4 * m_frame + line / 4);


for (int j = ((m_frame + 1) % 4) / 2 + jmin; j < jmax; j += 2)
for (int j = jmin; j < jmax; j += 2)
for (int i = m_frame % 2; i < m_size.x; i += 2) for (int i = m_frame % 2; i < m_size.x; i += 2)
{ {
f64cmplx z0 = m_center + TexelToWorldOffset(ivec2(i, j)); f64cmplx z0 = m_center + TexelToWorldOffset(ivec2(i, j));
@@ -659,6 +659,9 @@ DoWork(slice);


if (m_dirty[m_frame]) if (m_dirty[m_frame])
{ {
for (int i = 0; i < m_size.y; i += MAX_LINES * 2)
m_donequeue.Pop();

m_dirty[m_frame]--; m_dirty[m_frame]--;


#ifdef __CELLOS_LV2__ #ifdef __CELLOS_LV2__
@@ -718,8 +721,10 @@ DoWork(slice);
} }


private: private:
static int const MAX_ITERATIONS = 170;
static int const MAX_ITERATIONS = 340;
static int const PALETTE_STEP = 32; static int const PALETTE_STEP = 32;
static int const MAX_THREADS = 8;
static int const MAX_LINES = 8;


ivec2 m_size, m_window_size, m_oldmouse; ivec2 m_size, m_window_size, m_oldmouse;
double m_window2world; double m_window2world;
@@ -745,6 +750,10 @@ private:
f64cmplx m_deltashift[4]; f64cmplx m_deltashift[4];
double m_deltascale[4]; double m_deltascale[4];


/* Worker threads */
Thread *m_threads[MAX_THREADS];
Queue m_spawnqueue, m_jobqueue, m_donequeue;

/* Debug information */ /* Debug information */
#if !defined __native_client__ #if !defined __native_client__
Text *m_centertext, *m_mousetext, *m_zoomtext; Text *m_centertext, *m_mousetext, *m_zoomtext;


Loading…
取消
儲存