Я написал это для назначения класса ОС, которое я уже выполнил и передал. Вчера я опубликовал этот вопрос, но из-за правил "Академической честности" я снял его до истечения срока подачи заявки.
Целью было научиться использовать критические разделы. Существует массив 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.