Я написал это для назначения класса ОС, которое я уже выполнил и передал. Вчера я опубликовал этот вопрос, но из-за правил "Академической честности" я снял его до истечения срока подачи заявки.
Целью было научиться использовать критические разделы. Существует массив data с 100 монотонно увеличивающимися числами, 0... 99 и 40 потоками, которые случайным образом меняют местами два элемента по 20000 раз каждый. Через секунду проходит a Checker и удостоверяется, что есть только одно из каждого числа (что означает, что параллельный доступ не произошел).
Здесь были времена Linux:
real 0m5.102s
user 0m5.087s
sys 0m0.000s
и OS X раз
real 6m54.139s
user 0m41.873s
sys 6m43.792s
Я запускаю бродячий ящик с ubuntu/trusty64 на том же компьютере, на котором работает OS X. Это четырехъядерный i7 2.3Ghz (до 3.2 ГГц) 2012 rMBP.
Если я правильно понимаю, sys - это системные издержки, над которыми я не контролирую, и даже тогда 41 с пользовательского времени предполагает, что потоки выполняются серийно.
Я могу опубликовать весь код, если это необходимо, но я опубликую бит, которые, по моему мнению, актуальны. Я использую pthreads, так как это обеспечивает Linux, но я предположил, что они работают с OS X.
Создание swapper потоков для запуска swapManyTimes:
for (int i = 0; i < NUM_THREADS; i++) {
int err = pthread_create(&(threads[i]), NULL, swapManyTimes, NULL);
}
swapper секция критического потока, выполняемая в цикле for 2 миллиона раз:
pthread_mutex_lock(&mutex); // begin critical section
int tmpFirst = data[first];
data[first] = data[second];
data[second] = tmpFirst;
pthread_mutex_unlock(&mutex); // end critical section
Создается только один поток Checker, так же как swapper. Он работает, перейдя через массив data и маркируя индекс, соответствующий каждому значению, с помощью true. После этого он проверяет, сколько индексов пусто. как таковой:
pthread_mutex_lock(&mutex);
for (int i = 0; i < DATA_SIZE; i++) {
int value = data[i];
consistency[value] = 1;
}
pthread_mutex_unlock(&mutex);
Он запускается один раз в секунду, вызывая sleep(1) после выполнения цикла while(1). После того, как все теги swapper соединены, этот поток также отменяется и присоединяется.
Я был бы рад предоставить дополнительную информацию, которая поможет понять, почему это так сильно засасывает Mac. Я не ищу помощь в оптимизации кода, если только это не связано с OS X. Я попытался создать его с помощью clang и gcc-4.9 в OS X.