void oskar_interferometer_free(oskar_Interferometer* h, int* status)
{
    int i;
    if (!h) return;
    oskar_interferometer_reset_cache(h, status);
    for (i = 0; i < h->num_gpus; ++i)
    {
        oskar_device_set(h->gpu_ids[i], status);
        oskar_device_reset();
    }
    for (i = 0; i < h->num_sky_chunks; ++i)
        oskar_sky_free(h->sky_chunks[i], status);
    oskar_telescope_free(h->tel, status);
    oskar_mem_free(h->temp, status);
    oskar_timer_free(h->tmr_sim);
    oskar_timer_free(h->tmr_write);
    oskar_mutex_free(h->mutex);
    oskar_barrier_free(h->barrier);
    free(h->sky_chunks);
    free(h->gpu_ids);
    free(h->vis_name);
    free(h->ms_name);
    free(h->settings_path);
    free(h->d);
    free(h);
}
Example #2
0
void oskar_imager_free(oskar_Imager* h, int* status)
{
    int i;
    if (!h) return;
    oskar_imager_reset_cache(h, status);
    oskar_mem_free(h->uu_im, status);
    oskar_mem_free(h->vv_im, status);
    oskar_mem_free(h->ww_im, status);
    oskar_mem_free(h->uu_tmp, status);
    oskar_mem_free(h->vv_tmp, status);
    oskar_mem_free(h->ww_tmp, status);
    oskar_mem_free(h->vis_im, status);
    oskar_mem_free(h->weight_im, status);
    oskar_mem_free(h->weight_tmp, status);
    oskar_mem_free(h->time_im, status);
    oskar_timer_free(h->tmr_grid_finalise);
    oskar_timer_free(h->tmr_grid_update);
    oskar_timer_free(h->tmr_init);
    oskar_timer_free(h->tmr_read);
    oskar_timer_free(h->tmr_write);
    oskar_mutex_free(h->mutex);
    oskar_imager_free_device_data(h, status);
    for (i = 0; i < h->num_files; ++i)
        free(h->input_files[i]);
    free(h->input_files);
    free(h->input_root);
    free(h->output_root);
    free(h->ms_column);
    free(h->gpu_ids);
    free(h->d);
    free(h);
}
int benchmark(int num_elements, int num_directions, OpType op_type,
        int loc, int precision, bool evaluate_2d, int niter, double& time_taken)
{
    int status = 0;
    int type = precision | OSKAR_COMPLEX;
    oskar_Mem *beam = 0, *signal = 0, *z = 0, *z_i = 0;
    oskar_Mem *x = oskar_mem_create(precision, loc, num_directions, &status);
    oskar_Mem *y = oskar_mem_create(precision, loc, num_directions, &status);
    oskar_Mem *x_i = oskar_mem_create(precision, loc, num_elements, &status);
    oskar_Mem *y_i = oskar_mem_create(precision, loc, num_elements, &status);
    oskar_Mem *weights = oskar_mem_create(type, loc, num_elements, &status);
    if (!evaluate_2d)
    {
        z = oskar_mem_create(precision, loc, num_directions, &status);
        z_i = oskar_mem_create(precision, loc, num_elements, &status);
    }
    if (op_type == O2C)
        beam = oskar_mem_create(type, loc, num_directions, &status);
    else if (op_type == C2C || op_type == M2M)
    {
        int num_signals = num_directions * num_elements;
        if (op_type == C2C)
        {
            beam = oskar_mem_create(type, loc, num_directions, &status);
            signal = oskar_mem_create(type, loc, num_signals, &status);
        }
        else
        {
            type |= OSKAR_MATRIX;
            beam = oskar_mem_create(type, loc, num_directions, &status);
            signal = oskar_mem_create(type, loc, num_signals, &status);
        }
    }

    oskar_Timer *tmr = oskar_timer_create(OSKAR_TIMER_NATIVE);
    if (!status)
    {
        oskar_timer_start(tmr);
        for (int i = 0; i < niter; ++i)
        {
            oskar_dftw(num_elements, 2.0 * M_PI, x_i, y_i, z_i, weights,
                    num_directions, x, y, z, signal, beam, &status);
        }
        time_taken = oskar_timer_elapsed(tmr);
    }

    // Free memory.
    oskar_timer_free(tmr);
    oskar_mem_free(x, &status);
    oskar_mem_free(y, &status);
    oskar_mem_free(z, &status);
    oskar_mem_free(x_i, &status);
    oskar_mem_free(y_i, &status);
    oskar_mem_free(z_i, &status);
    oskar_mem_free(weights, &status);
    oskar_mem_free(beam, &status);
    oskar_mem_free(signal, &status);

    return status;
}
Example #4
0
static void free_device_data(oskar_Simulator* h, int* status)
{
    int i;
    if (!h->d) return;
    for (i = 0; i < h->num_devices; ++i)
    {
        DeviceData* d = &(h->d[i]);
        if (!d) continue;
        if (i < h->num_gpus)
            oskar_device_set(h->gpu_ids[i], status);
        oskar_timer_free(d->tmr_compute);
        oskar_timer_free(d->tmr_copy);
        oskar_timer_free(d->tmr_clip);
        oskar_timer_free(d->tmr_E);
        oskar_timer_free(d->tmr_K);
        oskar_timer_free(d->tmr_join);
        oskar_timer_free(d->tmr_correlate);
        oskar_vis_block_free(d->vis_block_cpu[0], status);
        oskar_vis_block_free(d->vis_block_cpu[1], status);
        oskar_vis_block_free(d->vis_block, status);
        oskar_mem_free(d->u, status);
        oskar_mem_free(d->v, status);
        oskar_mem_free(d->w, status);
        oskar_sky_free(d->chunk, status);
        oskar_sky_free(d->chunk_clip, status);
        oskar_telescope_free(d->tel, status);
        oskar_station_work_free(d->station_work, status);
        oskar_jones_free(d->J, status);
        oskar_jones_free(d->E, status);
        oskar_jones_free(d->K, status);
        oskar_jones_free(d->R, status);
        memset(d, 0, sizeof(DeviceData));
    }
}
Example #5
0
int benchmark(int num_stations, int num_sources, int type,
        int jones_type, int loc, int use_extended, int use_time_ave, int niter,
        std::vector<double>& times)
{
    int status = 0;

    oskar_Timer* timer;
    timer = oskar_timer_create(loc == OSKAR_GPU ?
            OSKAR_TIMER_CUDA : OSKAR_TIMER_OMP);

    // Set up a test sky model, telescope model and Jones matrices.
    oskar_Telescope* tel = oskar_telescope_create(type, loc,
            num_stations, &status);
    oskar_Sky* sky = oskar_sky_create(type, loc, num_sources, &status);
    oskar_Jones* J = oskar_jones_create(jones_type, loc, num_stations,
            num_sources, &status);

    oskar_telescope_set_channel_bandwidth(tel, 1e6);
    oskar_telescope_set_time_average(tel, (double) use_time_ave);
    oskar_sky_set_use_extended(sky, use_extended);

    // Memory for visibility coordinates and output visibility slice.
    oskar_Mem *vis, *u, *v, *w;
    vis = oskar_mem_create(jones_type, loc, oskar_telescope_num_baselines(tel),
            &status);
    u = oskar_mem_create(type, loc, num_stations, &status);
    v = oskar_mem_create(type, loc, num_stations, &status);
    w = oskar_mem_create(type, loc, num_stations, &status);

    // Run benchmark.
    times.resize(niter);
    for (int i = 0; i < niter; ++i)
    {
        oskar_timer_start(timer);
        oskar_cross_correlate(vis, oskar_sky_num_sources(sky), J, sky, tel, u, v, w,
                0.0, 100e6, &status);
        times[i] = oskar_timer_elapsed(timer);
    }

    // Free memory.
    oskar_mem_free(u, &status);
    oskar_mem_free(v, &status);
    oskar_mem_free(w, &status);
    oskar_mem_free(vis, &status);
    oskar_jones_free(J, &status);
    oskar_telescope_free(tel, &status);
    oskar_sky_free(sky, &status);
    oskar_timer_free(timer);
    return status;
}
Example #6
0
TEST(Mem, random_uniform)
{
    int seed = 1;
    int c1 = 437;
    int c2 = 0;
    int c3 = 0xDECAFBAD;
    int n = 544357;
    int status = 0;
    double max_err = 0.0, avg_err = 0.0;
    oskar_Mem* v_cpu_f = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU, n, &status);
    oskar_Mem* v_gpu_f = oskar_mem_create(OSKAR_SINGLE, OSKAR_GPU, n, &status);
    oskar_Mem* v_cpu_d = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, n, &status);
    oskar_Mem* v_gpu_d = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, n, &status);
    oskar_Timer* tmr = oskar_timer_create(OSKAR_TIMER_CUDA);

    // Run in single precision.
    oskar_timer_start(tmr);
    oskar_mem_random_uniform(v_cpu_f, seed, c1, c2, c3, &status);
    report_time(n, "uniform", "single", "CPU", oskar_timer_elapsed(tmr));
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    oskar_timer_start(tmr);
    oskar_mem_random_uniform(v_gpu_f, seed, c1, c2, c3, &status);
    report_time(n, "uniform", "single", "GPU", oskar_timer_elapsed(tmr));
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Check consistency between CPU and GPU results.
    oskar_mem_evaluate_relative_error(v_gpu_f, v_cpu_f, 0,
            &max_err, &avg_err, 0, &status);
    EXPECT_LT(max_err, 1e-5);
    EXPECT_LT(avg_err, 1e-5);

    // Run in double precision.
    oskar_timer_start(tmr);
    oskar_mem_random_uniform(v_cpu_d, seed, c1, c2, c3, &status);
    report_time(n, "uniform", "double", "CPU", oskar_timer_elapsed(tmr));
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    oskar_timer_start(tmr);
    oskar_mem_random_uniform(v_gpu_d, seed, c1, c2, c3, &status);
    report_time(n, "uniform", "double", "GPU", oskar_timer_elapsed(tmr));
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Check consistency between CPU and GPU results.
    oskar_mem_evaluate_relative_error(v_gpu_d, v_cpu_d, 0,
            &max_err, &avg_err, 0, &status);
    EXPECT_LT(max_err, 1e-10);
    EXPECT_LT(avg_err, 1e-10);

    // Check consistency between single and double precision.
    oskar_mem_evaluate_relative_error(v_cpu_f, v_cpu_d, 0,
            &max_err, &avg_err, 0, &status);
    EXPECT_LT(max_err, 1e-5);
    EXPECT_LT(avg_err, 1e-5);

    if (save)
    {
        FILE* fhan = fopen("random_uniform.txt", "w");
        oskar_mem_save_ascii(fhan, 4, n, &status,
                v_cpu_f, v_gpu_f, v_cpu_d, v_gpu_d);
        fclose(fhan);
    }

    // Free memory.
    oskar_mem_free(v_cpu_f, &status);
    oskar_mem_free(v_gpu_f, &status);
    oskar_mem_free(v_cpu_d, &status);
    oskar_mem_free(v_gpu_d, &status);
    oskar_timer_free(tmr);
}
Example #7
0
    void runTest(int prec1, int prec2, int loc1, int loc2, int matrix,
            int extended, double time_average)
    {
        int num_baselines, status = 0, type;
        oskar_Mem *vis1, *vis2;
        oskar_Timer *timer1, *timer2;
        double time1, time2, frequency = 100e6;

        // Create the timers.
        timer1 = oskar_timer_create(loc1 == OSKAR_GPU ?
                OSKAR_TIMER_CUDA : OSKAR_TIMER_NATIVE);
        timer2 = oskar_timer_create(loc2 == OSKAR_GPU ?
                OSKAR_TIMER_CUDA : OSKAR_TIMER_NATIVE);

        // Run first part.
        createTestData(prec1, loc1, matrix);
        num_baselines = oskar_telescope_num_baselines(tel);
        type = prec1 | OSKAR_COMPLEX;
        if (matrix) type |= OSKAR_MATRIX;
        vis1 = oskar_mem_create(type, loc1, num_baselines, &status);
        oskar_mem_clear_contents(vis1, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_sky_set_use_extended(sky, extended);
        oskar_telescope_set_channel_bandwidth(tel, bandwidth);
        oskar_telescope_set_time_average(tel, time_average);
        oskar_timer_start(timer1);
        oskar_cross_correlate(vis1, oskar_sky_num_sources(sky), jones, sky,
                tel, u_, v_, w_, 1.0, frequency, &status);
        time1 = oskar_timer_elapsed(timer1);
        destroyTestData();
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Run second part.
        createTestData(prec2, loc2, matrix);
        num_baselines = oskar_telescope_num_baselines(tel);
        type = prec2 | OSKAR_COMPLEX;
        if (matrix) type |= OSKAR_MATRIX;
        vis2 = oskar_mem_create(type, loc2, num_baselines, &status);
        oskar_mem_clear_contents(vis2, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_sky_set_use_extended(sky, extended);
        oskar_telescope_set_channel_bandwidth(tel, bandwidth);
        oskar_telescope_set_time_average(tel, time_average);
        oskar_timer_start(timer2);
        oskar_cross_correlate(vis2, oskar_sky_num_sources(sky), jones, sky,
                tel, u_, v_, w_, 1.0, frequency, &status);
        time2 = oskar_timer_elapsed(timer2);
        destroyTestData();
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Destroy the timers.
        oskar_timer_free(timer1);
        oskar_timer_free(timer2);

        // Compare results.
        check_values(vis1, vis2);

        // Free memory.
        oskar_mem_free(vis1, &status);
        oskar_mem_free(vis2, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Record properties for test.
        RecordProperty("SourceType", extended ? "Gaussian" : "Point");
        RecordProperty("JonesType", matrix ? "Matrix" : "Scalar");
        RecordProperty("TimeSmearing", time_average == 0.0 ? "off" : "on");
        RecordProperty("Prec1", prec1 == OSKAR_SINGLE ? "Single" : "Double");
        RecordProperty("Loc1", loc1 == OSKAR_CPU ? "CPU" : "GPU");
        RecordProperty("Time1_ms", int(time1 * 1000));
        RecordProperty("Prec2", prec2 == OSKAR_SINGLE ? "Single" : "Double");
        RecordProperty("Loc2", loc2 == OSKAR_CPU ? "CPU" : "GPU");
        RecordProperty("Time2_ms", int(time2 * 1000));

#ifdef ALLOW_PRINTING
        // Print times.
        printf("  > %s. %s sources. Time smearing %s.\n",
                matrix ? "Matrix" : "Scalar",
                extended ? "Gaussian" : "Point",
                time_average == 0.0 ? "off" : "on");
        printf("    %s precision %s: %.2f ms, %s precision %s: %.2f ms\n",
                prec1 == OSKAR_SINGLE ? "Single" : "Double",
                loc1 == OSKAR_CPU ? "CPU" : "GPU",
                time1 * 1000.0,
                prec2 == OSKAR_SINGLE ? "Single" : "Double",
                loc2 == OSKAR_CPU ? "CPU" : "GPU",
                time2 * 1000.0);
#endif
    }
Example #8
0
TEST(prefix_sum, test)
{
    int n = 100000, status = 0, exclusive = 1;
    oskar_Mem* in_cpu = oskar_mem_create(OSKAR_INT, OSKAR_CPU, n, &status);
    oskar_Mem* out_cpu = oskar_mem_create(OSKAR_INT, OSKAR_CPU, n, &status);
    oskar_Timer* tmr = oskar_timer_create(OSKAR_TIMER_NATIVE);

    // Fill input with random integers from 0 to 9.
    int* t = oskar_mem_int(in_cpu, &status);
    srand(1556);
    for (int i = 0; i < n; ++i)
        t[i] = (int) (10.0 * rand() / ((double) RAND_MAX));
    t[0] = 3;

    // Run on CPU.
    oskar_timer_start(tmr);
    oskar_prefix_sum(n, in_cpu, out_cpu, 0, exclusive, &status);
    EXPECT_EQ(0, status);
    printf("Prefix sum on CPU took %.3f sec\n", oskar_timer_elapsed(tmr));

#ifdef OSKAR_HAVE_CUDA
    // Run on GPU with CUDA.
    oskar_Mem* in_gpu = oskar_mem_create_copy(in_cpu, OSKAR_GPU, &status);
    oskar_Mem* out_gpu = oskar_mem_create(OSKAR_INT, OSKAR_GPU, n, &status);
    oskar_timer_start(tmr);
    oskar_prefix_sum(n, in_gpu, out_gpu, 0, exclusive, &status);
    EXPECT_EQ(0, status);
    printf("Prefix sum on GPU took %.3f sec\n", oskar_timer_elapsed(tmr));

    // Check consistency between CPU and GPU results.
    oskar_Mem* out_cmp_gpu = oskar_mem_create_copy(out_gpu, OSKAR_CPU, &status);
    EXPECT_EQ(0, oskar_mem_different(out_cpu, out_cmp_gpu, n, &status));
#endif

#ifdef OSKAR_HAVE_OPENCL
    // Run on OpenCL.
    oskar_Mem* in_cl = oskar_mem_create_copy(in_cpu, OSKAR_CL, &status);
    oskar_Mem* out_cl = oskar_mem_create(OSKAR_INT, OSKAR_CL, n, &status);
    oskar_timer_start(tmr);
    printf("Using %s\n", oskar_cl_device_name());
    oskar_prefix_sum(n, in_cl, out_cl, 0, exclusive, &status);
    EXPECT_EQ(0, status);
    printf("Prefix sum on OpenCL took %.3f sec\n", oskar_timer_elapsed(tmr));

    // Check consistency between CPU and OpenCL results.
    oskar_Mem* out_cmp_cl = oskar_mem_create_copy(out_cl, OSKAR_CPU, &status);
    EXPECT_EQ(0, oskar_mem_different(out_cpu, out_cmp_cl, n, &status));
#endif

    if (save)
    {
        size_t num_mem = 1;
        FILE* fhan = fopen("prefix_sum_test.txt", "w");
#ifdef OSKAR_HAVE_CUDA
        num_mem += 1;
#endif
#ifdef OSKAR_HAVE_OPENCL
        num_mem += 1;
#endif
        oskar_mem_save_ascii(fhan, num_mem, n, &status, out_cpu
#ifdef OSKAR_HAVE_CUDA
                , out_cmp_gpu
#endif
#ifdef OSKAR_HAVE_OPENCL
                , out_cmp_cl
#endif
                );
        fclose(fhan);
    }

    // Clean up.
    oskar_timer_free(tmr);
    oskar_mem_free(in_cpu, &status);
    oskar_mem_free(out_cpu, &status);
#ifdef OSKAR_HAVE_CUDA
    oskar_mem_free(in_gpu, &status);
    oskar_mem_free(out_gpu, &status);
    oskar_mem_free(out_cmp_gpu, &status);
#endif
#ifdef OSKAR_HAVE_OPENCL
    oskar_mem_free(in_cl, &status);
    oskar_mem_free(out_cl, &status);
    oskar_mem_free(out_cmp_cl, &status);
#endif
}
    void runTest(int prec1, int prec2, int loc1, int loc2, int matrix)
    {
        int status = 0, type;
        oskar_Mem *beam1, *beam2;
        oskar_Timer *timer1, *timer2;
        double time1, time2;

        // Create the timers.
        timer1 = oskar_timer_create(loc1 == OSKAR_GPU ?
                OSKAR_TIMER_CUDA : OSKAR_TIMER_NATIVE);
        timer2 = oskar_timer_create(loc2 == OSKAR_GPU ?
                OSKAR_TIMER_CUDA : OSKAR_TIMER_NATIVE);

        // Run first part.
        type = prec1 | OSKAR_COMPLEX;
        if (matrix) type |= OSKAR_MATRIX;
        beam1 = oskar_mem_create(type, loc1, num_sources, &status);
        oskar_mem_clear_contents(beam1, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        createTestData(prec1, loc1, matrix);
        oskar_timer_start(timer1);
        oskar_evaluate_cross_power(num_sources, num_stations,
                jones, 0, beam1, &status);
        time1 = oskar_timer_elapsed(timer1);
        destroyTestData();
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Run second part.
        type = prec2 | OSKAR_COMPLEX;
        if (matrix) type |= OSKAR_MATRIX;
        beam2 = oskar_mem_create(type, loc2, num_sources, &status);
        oskar_mem_clear_contents(beam2, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        createTestData(prec2, loc2, matrix);
        oskar_timer_start(timer2);
        oskar_evaluate_cross_power(num_sources, num_stations,
                jones, 0, beam2, &status);
        time2 = oskar_timer_elapsed(timer2);
        destroyTestData();
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Destroy the timers.
        oskar_timer_free(timer1);
        oskar_timer_free(timer2);

        // Compare results.
        check_values(beam1, beam2);

        // Free memory.
        oskar_mem_free(beam1, &status);
        oskar_mem_free(beam2, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Record properties for test.
        RecordProperty("JonesType", matrix ? "Matrix" : "Scalar");
        RecordProperty("Prec1", prec1 == OSKAR_SINGLE ? "Single" : "Double");
        RecordProperty("Loc1", loc1 == OSKAR_CPU ? "CPU" : "GPU");
        RecordProperty("Time1_ms", int(time1 * 1000));
        RecordProperty("Prec2", prec2 == OSKAR_SINGLE ? "Single" : "Double");
        RecordProperty("Loc2", loc2 == OSKAR_CPU ? "CPU" : "GPU");
        RecordProperty("Time2_ms", int(time2 * 1000));

#ifdef ALLOW_PRINTING
        // Print times.
        printf("  > %s.\n", matrix ? "Matrix" : "Scalar");
        printf("    %s precision %s: %.2f ms, %s precision %s: %.2f ms\n",
                prec1 == OSKAR_SINGLE ? "Single" : "Double",
                loc1 == OSKAR_CPU ? "CPU" : "GPU",
                time1 * 1000.0,
                prec2 == OSKAR_SINGLE ? "Single" : "Double",
                loc2 == OSKAR_CPU ? "CPU" : "GPU",
                time2 * 1000.0);
#endif
    }
Example #10
0
int benchmark(int num_elements, int num_directions, OpType op_type,
        int loc, int precision, bool evaluate_2d, int niter, double& time_taken)
{
    int status = 0;

    // Create the timer.
    oskar_Timer *tmr = oskar_timer_create(OSKAR_TIMER_CUDA);

    oskar_Station* station = oskar_station_create(precision, loc,
            num_elements, &status);
    if (status) return status;
    station->array_is_3d = (evaluate_2d) ? OSKAR_FALSE : OSKAR_TRUE;

    oskar_Mem *x, *y, *z, *weights = 0, *beam = 0, *signal = 0;
    x = oskar_mem_create(precision, loc, num_directions, &status);
    y = oskar_mem_create(precision, loc, num_directions, &status);
    z = oskar_mem_create(precision, loc, num_directions, &status);
    if (status) return status;

    if (op_type == O2C)
    {
        int type = precision | OSKAR_COMPLEX;
        beam = oskar_mem_create(type, loc, num_directions, &status);
        weights = oskar_mem_create(type, loc, num_elements, &status);
        if (status) return status;

        oskar_timer_start(tmr);
        for (int i = 0; i < niter; ++i)
        {
            oskar_evaluate_array_pattern(beam, 2.0 * M_PI, station,
                    num_directions, x, y, z, weights, &status);
        }
        time_taken = oskar_timer_elapsed(tmr);
    }
    else if (op_type == C2C || op_type == M2M)
    {
        int type = precision | OSKAR_COMPLEX;
        int num_signals = num_directions * num_elements;

        weights = oskar_mem_create(type, loc, num_elements, &status);
        if (op_type == C2C)
        {
            beam = oskar_mem_create(type, loc, num_directions, &status);
            signal = oskar_mem_create(type, loc, num_signals, &status);
        }
        else
        {
            type |= OSKAR_MATRIX;
            beam = oskar_mem_create(type, loc, num_directions, &status);
            signal = oskar_mem_create(type, loc, num_signals, &status);
        }
        if (status) return status;

        oskar_timer_start(tmr);
        for (int i = 0; i < niter; ++i)
        {
            oskar_evaluate_array_pattern_hierarchical(beam, 2.0 * M_PI, station,
                    num_directions, x, y, z, signal, weights, &status);
        }
        time_taken = oskar_timer_elapsed(tmr);
    }

    // Destroy the timer.
    oskar_timer_free(tmr);

    // Free memory.
    oskar_station_free(station, &status);
    oskar_mem_free(x, &status);
    oskar_mem_free(y, &status);
    oskar_mem_free(z, &status);
    oskar_mem_free(weights, &status);
    oskar_mem_free(beam, &status);
    oskar_mem_free(signal, &status);

    return status;
}