#macos #pthreads #semaphore
#macos #pthreads #семафор
Вопрос:
Я планирую использовать семафоры pthreads и mach, чтобы попытаться в основном выполнить параллельные вычисления для ограниченного числа процессоров, и я не могу заставить тестовую программу работать. Прямо сейчас у меня есть что-то, что просто проходит через потоки и выводит некоторый идентификатор, чтобы я мог убедиться, что он работает. Код довольно прост, за исключением того, что я на OSX, поэтому мне приходится использовать семафоры mach вместо POSIX. Мой код приведен ниже
#include <iostream>
#include <pthread.h>
#include <semaphore.h>
#include <errno.h>
#include <mach/semaphore.h>
#include <mach/mach.h>
#define MAX_THREADS 256
semaphore_t free_CPU = 0;
void* t_function(void *arg) {
int* cur_number;
cur_number = (int*) arg;
kern_return_t test = semaphore_wait(free_CPU);
std::cout << "I am thread # " << *cur_number << ". Kernel return is " << test << std::endl;
semaphore_signal(free_CPU);
std::cout << "I am thread # " << *cur_number << ". I just signaled the semaphore." << std::endl;
pthread_exit(NULL);
}
int main (int argc, char * const argv[]) {
int num_reps = 10;
int n_threads = 1;
if (n_threads < MAX_THREADS) {
n_threads = 0;
} else {
n_threads = MAX_THREADS;
}
pthread_t threads[n_threads];
semaphore_create(mach_task_self(), amp;free_CPU, SYNC_POLICY_FIFO, 1);
// Loop over a bunch of things, feeding out to only nthreads threads at a time!
int i;
int* numbers = new int[num_reps];
for (i = 0; i < num_reps; i ) {
numbers[i] = i;
std::cout << "Throwing thread " << numbers[i] << std::endl;
int rc = pthread_create(amp;threads[i], NULL, amp;t_function, amp;numbers[i]);
if (rc) {
std::cout << "Failed to throw thread " << i << " Error: " << strerror(errno) << std::endl;
exit(1);
}
}
std::cout << "Threw all threads" << std::endl;
// Loop over threads to join
for (i = 0; i < num_reps; i ) {
std::cout << "Joining thread " << i << std::endl;
int rc = pthread_join(threads[i],NULL);
if (rc) {
std::cout << "Failed to join thread " << i << ". Error: " << strerror(errno) << std::endl;
exit(1);
}
}
semaphore_destroy(mach_task_self(), free_CPU);
delete[] numbers;
return 0;
}
Запуск этого кода дает мне:
Throwing thread 0
Throwing thread 1
Throwing thread 2
Throwing thread 3
Throwing thread 4
Throwing thread 5
Throwing thread 6
Throwing thread 7
Throwing thread 8
Throwing thread 9
Threw all threads
Joining thread 0
I am thread # 0. Kernel return is 0
I am thread # 0. I just signaled the semaphore.
I am thread # 1. Kernel return is 0
I am thread # 1. I just signaled the semaphore.
I am thread # 2. Kernel return is 0
I am thread # 2. I just signaled the semaphore.
I am thread # 3. Kernel return is 0
I am thread # 3. I just signaled the semaphore.
I am thread # 4. Kernel return is 0
I am thread # 4. I just signaled the semaphore.
I am thread # 5. Kernel return is 0
I am thread # 5. I just signaled the semaphore.
I am thread # 6. Kernel return is 0
I am thread # 6. I just signaled the semaphore.
I am thread # 7. Kernel return is 0
I am thread # 7. I just signaled the semaphore.
I am thread # 8. Kernel return is 0
I am thread # 8. I just signaled the semaphore.
I am thread # 9. Kernel return is 0
I am thread # 9. I just signaled the semaphore.
Joining thread 1
Joining thread 2
Joining thread 3
Joining thread 4
Joining thread 5
Joining thread 6
Joining thread 7
Joining thread 8
Failed to join thread 8. Error: Unknown error: 0
Для меня похоже, что все в полном порядке, за исключением того, что он просто кусает пыль, когда пытается присоединиться к потоку 8. Я понятия не имею, что происходит.
Ответ №1:
Ваша проблема заключается здесь:
#define MAX_THREADS 256
:
int n_threads = 1;
if (n_threads < MAX_THREADS) {
n_threads = 0;
} else {
n_threads = MAX_THREADS;
}
pthread_t threads[n_threads];
Это дает вам массив с одним идентификатором потока. Затем вы пытаетесь заполнить десять из них.
Я не совсем уверен, чего вы пытаетесь достичь с этим. Мне кажется, что если бы вы просто использовали num_reps
размер вашего массива, он работал бы нормально (вы получили бы массив из десяти элементов).
Комментарии:
1. О боже, большое спасибо. Я полагал, что это будет что-то вроде этого. 🙂
2. @user1013641: не нужно называть меня богом, pax отлично справится 🙂