/*******************************************************************************
* This file is part of SWIFT.
* Copyright (C) 2016 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
* Copyright (C) 2020 Peter W. Draper (p.w.draper@durham.ac.uk)
*
* 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 .
*
******************************************************************************/
#include
// Standard includes.
#include
#include
#include
// Local includes.
#include "../src/atomic.h"
#include "../src/threadpool.h"
void map_function_first(void *map_data, int num_elements, void *extra_data) {
const int *inputs = (int *)map_data;
for (int ind = 0; ind < num_elements; ind++) {
int input = inputs[ind];
usleep(rand() % 1000000);
printf(" map_function_first: got input %i.\n", input);
fflush(stdout);
}
}
void map_function_second(void *map_data, int num_elements, void *extra_data) {
const int *inputs = (int *)map_data;
for (int ind = 0; ind < num_elements; ind++) {
int input = inputs[ind];
usleep(rand() % 1000000);
printf(" map_function_second: got input %i.\n", input);
fflush(stdout);
}
}
void map_function_check_uniform(void *map_data, int num_elements,
void *extra_data) {
const int *inputs = (int *)map_data;
int count = inputs[0];
if (num_elements == 1) {
/* Single element. Sum this in the extra_data counter. Should
* be the sum of counts when threadpool is completed. */
atomic_add((int *)extra_data, count);
} else {
for (int ind = 1; ind < num_elements; ind++) {
if (inputs[ind] != count + 1) {
printf(" uniform chunking not correct, out of sequence\n");
fflush(stdout);
exit(1);
}
count = inputs[ind];
}
}
printf(" map_function_check_uniform handled %d elements\n", num_elements);
}
int main(int argc, char *argv[]) {
// Some constants for this test.
const int N = 20;
const int num_runs = 2;
// Create threadpools with different numbers of threads.
for (int num_thread = 1; num_thread <= 16; num_thread *= 4) {
printf("# Creating threadpool with %d threads\n", num_thread);
struct threadpool tp;
threadpool_init(&tp, num_thread);
// Main loop.
for (int run = 0; run < num_runs; run++) {
// Run over a set of integers and print them.
int data[N];
for (int k = 0; k < N; k++) data[k] = k;
printf("1..processing integers from 0..%i.\n", N);
fflush(stdout);
threadpool_map(&tp, map_function_first, data, N, sizeof(int), 1, NULL);
// Do the same thing again, with less jobs than threads.
printf("2..processing integers from 0..%i.\n", N / 2);
fflush(stdout);
threadpool_map(&tp, map_function_second, data, N / 2, sizeof(int), 1,
NULL);
// Do the same thing again, with a chunk size of two.
printf("3..processing integers from 0..%i.\n", N);
fflush(stdout);
threadpool_map(&tp, map_function_first, data, N, sizeof(int), 2, NULL);
}
/* If logging was enabled, dump the log. */
#ifdef SWIFT_DEBUG_THREADPOOL
char filename[80];
sprintf(filename, "threadpool_log-%d.txt", num_thread);
printf("# Dumping log\n");
threadpool_dump_log(&tp, filename, 1);
#endif
/* Be clean */
threadpool_clean(&tp);
printf("\n");
}
printf("# threadpool_uniform_chunk_size checks\n");
/* Check the spread of threads with threadpool_uniform_chunk_size */
int counts[23];
for (int i = 0; i < 23; i++) counts[i] = i;
struct threadpool utp;
int unum_thread = 7;
threadpool_init(&utp, unum_thread);
/* Under provision of threads. */
int dummy;
printf("# under provision\n");
threadpool_map(&utp, map_function_check_uniform, counts, 23, sizeof(int),
threadpool_uniform_chunk_size, &dummy);
/* Over provision of threads. */
int sum = 0;
for (int i = 0; i < 5; i++) sum += i;
static int lsum = 0;
printf("# over provision\n");
threadpool_map(&utp, map_function_check_uniform, counts, 5, sizeof(int),
threadpool_uniform_chunk_size, &lsum);
if (lsum != sum) {
printf(
" uniform chunking not correct, sum of tids failed "
"(%d != %d).\n",
sum, lsum);
fflush(stdout);
exit(1);
}
/* Exact provision of threads. */
sum = 0;
for (int i = 0; i < unum_thread; i++) sum += i;
lsum = 0;
printf("# exact provision\n");
threadpool_map(&utp, map_function_check_uniform, counts, unum_thread,
sizeof(int), threadpool_uniform_chunk_size, &lsum);
if (lsum != sum) {
printf(
" uniform chunking not correct, sum of tids failed "
"(%d != %d).\n",
sum, lsum);
fflush(stdout);
exit(1);
}
threadpool_clean(&utp);
printf("# passed uniform checks\n");
return 0;
}