/******************************************************************************* * This file is part of SWIFT. * Copyright (C) 2020 Matthieu Schaller (schaller@strw.leidenuniv.nl) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * ******************************************************************************/ /* Config parameters. */ #include /* Standard includes. */ #include /* Local includes */ #include "swift.h" const int array_size = 2048 * 2048; const int num_threads = 64; const int chunk_size = 64; void map_function_sum_f(void *data, int num_elements, void *extra_data) { float *array = (float *)data; float *sum = (float *)extra_data; for (int i = 0; i < num_elements; ++i) atomic_add_f(sum, array[i]); } void map_function_sum_ll(void *data, int num_elements, void *extra_data) { long long *array = (long long *)data; long long *sum = (long long *)extra_data; for (int i = 0; i < num_elements; ++i) atomic_add(sum, array[i]); } void map_function_inc_ll(void *data, int num_elements, void *extra_data) { long long *sum = (long long *)extra_data; for (int i = 0; i < num_elements; ++i) atomic_inc(sum); } int main(int argc, char *argv[]) { /* Initialize CPU frequency, this also starts time. */ unsigned long long cpufreq = 0; clocks_set_cpufreq(cpufreq); /* Choke on FPEs */ #ifdef HAVE_FE_ENABLE_EXCEPT feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); #endif /* Get some randomness going */ const int seed = time(NULL); message("Seed = %d", seed); srand(seed); /* Start a bunch of threads */ printf("# Creating threadpool with %d threads\n", num_threads); struct threadpool tp; threadpool_init(&tp, num_threads); /* Create some random data */ float *array_f = (float *)malloc(array_size * sizeof(float)); long long *array_ll = (long long *)malloc(array_size * sizeof(long long)); for (int i = 0; i < array_size; ++i) { array_f[i] = rand() / ((float)RAND_MAX); array_ll[i] = rand(); } /*** Test the addition atomic ops *******************************/ /* float case */ /* Compute the real answer */ float real_sum_f = 0.f; for (int i = 0; i < array_size; ++i) { real_sum_f += array_f[i]; } /* Compute the answer via threads and atomic */ float atomic_sum_f = 0.f; threadpool_map(&tp, map_function_sum_f, array_f, array_size, sizeof(float), chunk_size, &atomic_sum_f); const double diff_sum_f = (double)real_sum_f - (double)atomic_sum_f; const double sum_sum_f = (double)real_sum_f + (double)atomic_sum_f; const double rel_sum_f = 0.5 * fabs(diff_sum_f) / sum_sum_f; message("Real sum = %.7e -- atomic sum = %.7e rel=%e", real_sum_f, atomic_sum_f, rel_sum_f); /* long long case */ /* Compute the real answer */ long long real_sum_ll = 0.f; for (int i = 0; i < array_size; ++i) { real_sum_ll += array_ll[i]; } /* Compute the answer via threads and atomic */ long long atomic_sum_ll = 0LL; threadpool_map(&tp, map_function_sum_ll, array_ll, array_size, sizeof(long long), chunk_size, &atomic_sum_ll); const double diff_sum_ll = (double)real_sum_ll - (double)atomic_sum_ll; const double sum_sum_ll = (double)real_sum_ll + (double)atomic_sum_ll; const double rel_sum_ll = 0.5 * fabs(diff_sum_ll) / sum_sum_ll; message("Real sum = %lld -- atomic sum = %lld rel=%e", real_sum_ll, atomic_sum_ll, rel_sum_ll); /*** Test the inc atomic ops *******************************/ long long real_inc_ll = array_size; /* Compute the answer via threads and atomic */ long long atomic_inc_ll = 0LL; threadpool_map(&tp, map_function_inc_ll, array_ll, array_size, sizeof(long long), chunk_size, &atomic_inc_ll); const double diff_inc_ll = (double)real_inc_ll - (double)atomic_inc_ll; const double sum_inc_ll = (double)real_inc_ll + (double)atomic_inc_ll; const double rel_inc_ll = 0.5 * fabs(diff_inc_ll) / sum_inc_ll; message("Real inc = %lld -- atomic inc = %lld rel=%e", real_inc_ll, atomic_inc_ll, rel_inc_ll); /* Be clean */ threadpool_clean(&tp); free(array_f); free(array_ll); return 0; }