Changeset 1102


Ignore:
Timestamp:
Nov 30, 2011, 10:00:29 PM (9 years ago)
Author:
sam
Message:

test: proper multithreading in the Mandelbrot tutorial.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/test/tutorial/tut03.cpp

    r1100 r1102  
    105105            double f = (double)i / PALETTE_STEP;
    106106
    107             double r = 0.5 * sin(f * 0.27 - 2.5) + 0.5;
    108             double g = 0.5 * sin(f * 0.13 + 1.1) + 0.5;
    109             double b = 0.5 * sin(f * 0.21 + 0.4) + 0.5;
     107            double r = 0.5 * sin(f * 0.27 + 2.0) + 0.5;
     108            double g = 0.5 * sin(f * 0.17 - 1.8) + 0.5;
     109            double b = 0.5 * sin(f * 0.21 - 2.6) + 0.5;
    110110
    111111            if (f < 7.0)
     
    147147        bbox[1] = ivec3(m_window_size, 0);
    148148        Input::TrackMouse(this);
     149
     150        /* Spawn worker threads and wait for their readiness. */
     151        for (int i = 0; i < MAX_THREADS; i++)
     152            m_threads[i] = new Thread(DoWorkHelper, this);
     153        for (int i = 0; i < MAX_THREADS; i++)
     154            m_spawnqueue.Pop();
    149155    }
    150156
    151157    ~Fractal()
    152158    {
     159        /* Signal worker threads for completion. */
     160        for (int i = 0; i < MAX_THREADS; i++)
     161            m_jobqueue.Push(-1);
     162
    153163        Input::UntrackMouse(this);
    154164#if !defined __native_client__
     
    308318            m_dirty[m_frame]--;
    309319
    310             /* FIXME: this is the ugliest, most pathetic excuse for a
    311              * threading system that I have seen in a while. */
    312             DoWorkHelper helpers[m_slices];
    313             for (int slice = 0; slice < m_slices; slice++)
    314             {
    315                 helpers[slice].fractal = this;
    316                 helpers[slice].slice = slice;
    317 //                helpers[slice].thread = new Thread(DoWorkHelper::Help,
    318 //                                                   &helpers[slice]);
    319 DoWork(slice);
    320             }
    321             for (int slice = 0; slice < m_slices; slice++)
    322             {
    323 //                delete helpers[slice].thread;
    324             }
     320            for (int i = 0; i < m_size.y; i += MAX_LINES * 2)
     321                m_jobqueue.Push(i);
    325322        }
    326323    }
    327324
    328     struct DoWorkHelper
     325    static void *DoWorkHelper(void *data)
    329326    {
    330         Fractal *fractal;
    331         Thread *thread;
    332         int slice;
    333 
    334         static void *Help(void *data)
    335         {
    336             DoWorkHelper *helper = (DoWorkHelper *)data;
    337             helper->fractal->DoWork(helper->slice);
    338             return NULL;
    339         }
     327        Fractal *that = (Fractal *)data;
     328        that->m_spawnqueue.Push(0);
     329        for ( ; ; )
     330        {
     331            int line = that->m_jobqueue.Pop();
     332            if (line == -1)
     333                break;
     334            that->DoWork(line);
     335            that->m_donequeue.Push(0);
     336        }
     337        return NULL;
    340338    };
    341339
    342     void DoWork(int slice)
     340    void DoWork(int line)
    343341    {
    344342        double const maxsqlen = 1024;
    345343        double const k1 = 1.0 / (1 << 10) / log2(maxsqlen);
    346344
    347         int jmin = m_size.y * slice / m_slices;
    348         int jmax = m_size.y * (slice + 1) / m_slices;
     345        int jmin = ((m_frame + 1) % 4) / 2 + line;
     346        int jmax = jmin + MAX_LINES * 2;
     347        if (jmax > m_size.y)
     348            jmax = m_size.y;
    349349        u8vec4 *m_pixelstart = m_pixels
    350                              + m_size.x * (m_size.y / 4 * m_frame + jmin / 4);
    351 
    352         for (int j = ((m_frame + 1) % 4) / 2 + jmin; j < jmax; j += 2)
     350                             + m_size.x * (m_size.y / 4 * m_frame + line / 4);
     351
     352        for (int j = jmin; j < jmax; j += 2)
    353353        for (int i = m_frame % 2; i < m_size.x; i += 2)
    354354        {
     
    660660        if (m_dirty[m_frame])
    661661        {
     662            for (int i = 0; i < m_size.y; i += MAX_LINES * 2)
     663                m_donequeue.Pop();
     664
    662665            m_dirty[m_frame]--;
    663666
     
    719722
    720723private:
    721     static int const MAX_ITERATIONS = 170;
     724    static int const MAX_ITERATIONS = 340;
    722725    static int const PALETTE_STEP = 32;
     726    static int const MAX_THREADS = 8;
     727    static int const MAX_LINES = 8;
    723728
    724729    ivec2 m_size, m_window_size, m_oldmouse;
     
    746751    double m_deltascale[4];
    747752
     753    /* Worker threads */
     754    Thread *m_threads[MAX_THREADS];
     755    Queue m_spawnqueue, m_jobqueue, m_donequeue;
     756
    748757    /* Debug information */
    749758#if !defined __native_client__
Note: See TracChangeset for help on using the changeset viewer.