Я думаю, что мы можем упростить ваш код, избежать всех этих ненужных вызовов malloc и упростить ваш алгоритм для нахождения пары min / max в массиве.
Начнем с того, что функция потока, которая принимает в качестве входных данныхследующее: массив (представленный указателем), индекс в массиве, с которого нужно начать поиск, и индекс в массиве, где остановиться.Кроме того, для этой функции потребуются два выходных параметра - самое маленькое и самое большое целое число, найденное в найденном подмножестве массива.
Начните с объявления параметра.Аналогичен вашему MaxMin, но имеет как входные, так и выходные параметры:
struct ThreadParameters
{
// input
int* array;
int start;
int end;
// output
int smallest;
int largest;
};
И затем функция потока, которая сканирует от array[start]
до (но не включая) array[end]
.И он помещает результаты своего сканирования в smallest
и largest
член вышеупомянутой структуры:
void* find_min_max(void* args)
{
struct ThreadParameters* params = (struct ThreadParameters*)args;
int *array = params->array;
int start = params->start;
int end = params->end;
int smallest = array[start];
int largest = array[start];
for (int i = start; i < end; i++)
{
if (array[i] < smallest)
{
smallest = array[i];
}
if (array[i] > largest)
{
largest = array[i];
}
}
// write the result back to the parameter structure
params->smallest = smallest;
params->largest = largest;
return NULL;
}
И пока мы находимся в этом, используйте капитальные буквы для ваших макросов:
#define THREAD_COUNT 4
Теперь вы можете сохранить дизайн «4 отдельных массива».Но нет никаких причин, так как функция потока может сканировать любой диапазон любого массива.Итак, давайте объявим один глобальный массив следующим образом:
#define ARRAY_SIZE 400
int arr[ARRAY_SIZE];
Синтаксис буквы капитала предпочтителен для макросов.
fillArray
становится проще:
void fillArray()
{
for (int i = 0; i < ARRAY_SIZE; i++)
{
arr[i] = rand() % 1000 + 1;
}
}
Сейчасmain, с помощью этих методов становится намного проще.:
Мы будем использовать стек для распределения нашей структуры параметров потока (без malloc и free)
Мы просто запустим 4 потока - передавая каждому потоку указатель в структуру ThreadParameter.Поскольку поток не переживет main
, это безопасно.
После запуска каждого потока, мы просто ждем окончания каждого потока)
Затем мы просматриваем список параметров потока, чтобы получить последние наименьшие и наибольшие значения.
main
становится намного проще в управлении:
int main()
{
int smallest;
int largest;
// declare an array of threads and associated parameter instances
pthread_t threads[THREAD_COUNT] = {0};
struct ThreadParameters thread_parameters[THREAD_COUNT] = {0};
// intialize the array
fillArray();
// smallest and largest needs to be set to something
smallest = arr[0];
largest = arr[0];
// start all the threads
for (int i = 0; i < THREAD_COUNT; i++)
{
thread_parameters[i].array = arr;
thread_parameters[i].start = i * (ARRAY_SIZE / THREAD_COUNT);
thread_parameters[i].end = (i+1) * (ARRAY_SIZE / THREAD_COUNT);
thread_parameters[i].largest = 0;
pthread_create(&threads[i], NULL, find_min_max, &thread_parameters[i]);
}
// wait for all the threads to complete
for (int i = 0; i < THREAD_COUNT; i++)
{
pthread_join(threads[i], NULL);
}
// Now aggregate the "smallest" and "largest" results from all thread runs
for (int i = 0; i < THREAD_COUNT; i++)
{
if (thread_parameters[i].smallest < smallest)
{
smallest = thread_parameters[i].smallest;
}
if (thread_parameters[i].largest > largest)
{
largest = thread_parameters[i].largest;
}
}
printf("Smallest is %d\n", smallest);
printf("Largest is %d\n", largest);
}