Exemplo n.º 1
0
    virtual void HandleMessage(const Var& var_message) {

        if (busy) return;
        busy = true;

        static int thread_pool_size = 8;
        static int halide_last_t = 0;
        static int halide_time_weight = 0;
        static int last_demo = -1;

        int demo = 0;

        if (var_message.is_string()) {
            std::string msg = var_message.AsString();
            int threads = atoi(msg.c_str()+2);
            if (threads < 1) threads = 1;
            if (threads > 32) threads = 32;
            if (threads > 0 && threads <= 32 && thread_pool_size != threads) {
                halide_shutdown_thread_pool();
                thread_pool_size = threads;
                char buf[256];
                snprintf(buf, 256, "%d", threads);
                setenv("HL_NUMTHREADS", buf, 1);
                halide_last_t = 0;
                halide_time_weight = 0;
            }
            demo = msg[0] - '0';
        }

        static bool first_run = true;
        if (first_run) {
            first_run = false;
            setenv("HL_NUMTHREADS", "8", 1);
        }

        // Initialize the input
        if (demo != last_demo) {
            last_demo = demo;

            // Delete any existing state
            free_buffer(&state_1);
            free_buffer(&state_2);

            halide_last_t = 0;
            halide_time_weight = 0;

            switch (demo) {
            case 0:
                // Query how large the state arrays need to be in
                // order to hit our render target using Halide's
                // bounds query mode.
                game_of_life_render(&state_1, &render_target);
                state_2 = state_1;
                alloc_buffer(&state_1);
                alloc_buffer(&state_2);
                // Initialize into the first one
                game_of_life_init(&state_1);
                break;
            case 1:
                julia_render(&state_1, &render_target);
                state_2 = state_1;
                alloc_buffer(&state_1);
                alloc_buffer(&state_2);
                julia_init(&state_1);
                break;
            case 2:
                reaction_diffusion_render(&state_1, &render_target);
                state_2 = state_1;
                alloc_buffer(&state_1);
                alloc_buffer(&state_2);
                print_buffer(&state_1);
                reaction_diffusion_init(&state_1);
                break;
            case 3:
                reaction_diffusion_2_render(&state_1, &render_target);
                state_2 = state_1;
                alloc_buffer(&state_1);
                alloc_buffer(&state_2);
                print_buffer(&state_1);
                reaction_diffusion_2_init(&state_1);
                break;
            default:
                PostMessage("Bad demo index");
                return;
            }
        }

        if (pipeline_barfed) {
            return;
        }

        timeval t1, t2;
        gettimeofday(&t1, NULL);
        switch (demo) {
        case 0:
            game_of_life_update(&state_1, mouse_x, mouse_y, &state_2);
            game_of_life_render(&state_2, &render_target);
            break;
        case 1:
            julia_update(&state_1, mouse_x, mouse_y, &state_2);
            julia_render(&state_2, &render_target);
            break;
        case 2:
            reaction_diffusion_update(&state_1, mouse_x, mouse_y, &state_2);
            reaction_diffusion_render(&state_2, &render_target);
            break;
        case 3:
            reaction_diffusion_2_update(&state_1, mouse_x, mouse_y, &state_2);
            reaction_diffusion_2_render(&state_2, &render_target);
            break;
        }
        gettimeofday(&t2, NULL);
        std::swap(state_1, state_2);

        mouse_x = mouse_y = -100;

        if (pipeline_barfed) {
            return;
        }

        int t = t2.tv_usec - t1.tv_usec;
        t += (t2.tv_sec - t1.tv_sec)*1000000;

        // Smooth it out so we can see a rolling average
        t = (halide_last_t * halide_time_weight + t) / (halide_time_weight + 1);
        halide_last_t = t;
        if (halide_time_weight < 100) {
            halide_time_weight++;
        }

        std::ostringstream oss;
        oss << "<table cellspacing=8><tr><td width=200 height=30>Halide routine takes:</td><td>";
        if (halide_time_weight < 10) {
            oss << "?";
        } else {
            oss << halide_last_t;
        }
        oss << " us</td></tr></table>";

        PostMessage(oss.str());

        graphics.PaintImageData(framebuffer, Point(0, 0));
        graphics.Flush(callback);
    }
Exemplo n.º 2
0
    /// Handler for messages coming in from the browser via postMessage().  The
    /// @a var_message can contain anything: a JSON string; a string that encodes
    /// method names and arguments; etc.  For example, you could use
    /// JSON.stringify in the browser to create a message that contains a method
    /// name and some parameters, something like this:
    ///   var json_message = JSON.stringify({ "myMethod" : "3.14159" });
    ///   nacl_module.postMessage(json_message);
    /// On receipt of this message in @a var_message, you could parse the JSON to
    /// retrieve the method name, match it to a function call, and then call it
    /// with the parameter.
    /// @param[in] var_message The message posted by the browser.
    virtual void HandleMessage(const Var& var_message) {

        if (busy) return;
        busy = true;

        static int thread_pool_size = 8;
        static int halide_last_t = 0;
        static int halide_time_weight = 0;
        static int c_last_t = 0;
        static int c_time_weight = 0;
        static bool use_halide = true;

        if (var_message.is_string()) {            
            std::string msg = var_message.AsString();
            int threads = atoi(msg.c_str()+2);
            if (threads < 1) threads = 1;
            if (threads > 32) threads = 32;
            if (threads > 0 && threads <= 32 && thread_pool_size != threads) {
                halide_shutdown_thread_pool();
                thread_pool_size = threads;
                char buf[256];
                snprintf(buf, 256, "%d", threads);
                setenv("HL_NUMTHREADS", buf, 1);
                halide_last_t = 0;
                halide_time_weight = 0;
            }

            bool new_use_halide = (msg[0] == '0');
            if (new_use_halide != use_halide) {
                use_halide = new_use_halide;
            }
        }

        buffer_t input = ImageToBuffer(im1);
        buffer_t output = ImageToBuffer(im2);

        // Only compute the inner part of output so that we don't have
        // to worry about boundary conditions.
        output.min[0] = output.min[1] = MARGIN;
        output.extent[0] -= MARGIN*2;
        output.extent[1] -= MARGIN*2;
        output.host += (output.stride[1] + output.stride[0]) * MARGIN * 4;

        // Initialize the input with noise
        static bool first_run = true;
        if (first_run) {
            first_run = false; 

            // Start with 8 threads
            setenv("HL_NUMTHREADS", "8", 1);

            //  Initialize the buffers                        
            memset(im2.data(), 0, im2.stride() * im2.size().height());

            for (int y = 0; y < HEIGHT; y++) {
                uint8_t *ptr = ((uint8_t *)im1.data()) + im1.stride() * y;
                for (int x = 0; x < WIDTH; x++) {
                    ptr[x*4] = ((rand() & 31) == 0) ? 255 : 0;
                    ptr[x*4+1] = ((rand() & 31) == 0) ? 255 : 0;
                    ptr[x*4+2] = ((rand() & 31) == 0) ? 255 : 0;                
                    ptr[x*4+3] = (x >= MARGIN && 
                                  (x < (WIDTH - MARGIN)) && 
                                   y >= MARGIN && 
                                   y < (HEIGHT - MARGIN)) ? 255 : 0;
                }
            }            
                
        }
        
        timeval t1, t2;
        gettimeofday(&t1, NULL);
        if (use_halide) {
            halide_game_of_life(&input, &output);
        } else {
            c_game_of_life(&input, &output);
        }
        gettimeofday(&t2, NULL);        

        if (pipeline_barfed) return;

        int t = t2.tv_usec - t1.tv_usec;
        t += (t2.tv_sec - t1.tv_sec)*1000000;

        // Smooth it out so we can see a rolling average
        if (use_halide) {
            t = (halide_last_t * halide_time_weight + t) / (halide_time_weight + 1);
            halide_last_t = t;
            if (halide_time_weight < 100) {
                halide_time_weight++;
            }
        } else {
            t = (c_last_t * c_time_weight + t) / (c_time_weight + 1);
            c_last_t = t;
            if (c_time_weight < 100) {
                c_time_weight++;
            }
        }

        std::ostringstream oss;
        oss << "<table cellspacing=8><tr><td width=200 height=30>Halide routine takes:</td><td>";
        if (halide_time_weight < 10) {
            oss << "?";
        } else {
            if (use_halide) oss << "<b>";
            oss << halide_last_t;
            if (use_halide) oss << "</b>";
        }
        oss << " us</td></tr><tr><td width=200 height=30>Scalar C routine takes:</td><td>";
        if (c_time_weight < 10) {
            oss << "?";
        } else {
            if (!use_halide) oss << "<b>";
            oss << c_last_t;
            if (!use_halide) oss << "</b>";
        }
        oss << " us</td></tr></table>";

        PostMessage(oss.str());

        graphics.PaintImageData(im2, Point(0, 0));

        graphics.Flush(callback);         

        std::swap(im1, im2);
    }