Сравнивая потоки Haskell с потоками ядра - мой тест жизнеспособен? - PullRequest
3 голосов
/ 08 мая 2011

Это на самом деле для моего университетского проекта.В моем эссе мне нужно привести доказательства того, что потоки на Haskell создаются быстрее, чем простые потоки ядра.Я знаю, что лучше обратиться к какой-нибудь исследовательской работе, но суть в том, что я должен провести сравнительный анализ самостоятельно.

Вот что я придумал.Я написал две программы на C (с использованием pthreads) и Haskell, которые создают много потоков, но эти потоки абсолютно ничего не делают.Мне нужно измерить только скорость создания потока.

Вот исходный код для программы на C:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

void* thread_main(void*);

int main(int argc, char* argv[])
{
   int n,i;
    pthread_t *threads;
    pthread_attr_t pthread_custom_attr;

    if (argc != 2)
    {
        printf ("Usage: %s n\n  where n is no. of threads\n",argv[0]);
       return 1;
   }

    n=atoi(argv[1]);

    threads=(pthread_t *)malloc(n*sizeof(*threads));
    pthread_attr_init(&pthread_custom_attr);

    for (i=0; i<n; i++)
    {
        pthread_create(&threads[i], &pthread_custom_attr, thread_main, (void *)(0));
    }

    for (i=0; i<n; i++)
    {
        pthread_join(threads[i],NULL);
    }
}

void* thread_main(void* p)
{
   return 0;
}

и для программы на Haskell:

module Main (main) where

import System.IO.Unsafe
import System
import Control.Concurrent
import Control.Exception

children :: MVar [MVar ()]
children = unsafePerformIO (newMVar [])

waitForChildren :: IO ()
waitForChildren = do
   cs <- takeMVar children
   case cs of
      []   -> return ()
      m:ms -> do
         putMVar children ms
         takeMVar m
         waitForChildren

forkChild :: IO () -> IO ThreadId
forkChild io = do
   mvar <- newEmptyMVar
   childs <- takeMVar children
   putMVar children (mvar:childs)
   forkIO (io `finally` putMVar mvar ())

forkKids :: Int -> IO ()
forkKids 0 = return ()
forkKids n = do
   forkChild (threadMain)
   forkKids (n-1)

threadMain = return ()

main = do
   args <- getArgs
   forkKids (read (head args))
   waitForChildren

Теперь я запускаю каждую программу с одним и тем же аргументом (например, 10000) и измеряю их время выполнения с помощью time -f%e, а затем беру среднее арифметическое времени выполнения.Это показывает, что создание потоков на Haskell на порядок быстрее.

Теперь мой вопрос: правильный ли это тест?или есть какой-то фактор, который мне нужно учитывать, чтобы получить точные результаты?

Спасибо

Ответы [ 2 ]

4 голосов
/ 08 мая 2011

Ваши тесты, вероятно, дают вам желаемый результат, но там очень много шума. Вы измеряете не «сколько времени занимает создание потока», а «сколько времени требуется для запуска и запуска программы, которая создает несколько потоков, а затем ждет их возврата, прежде чем завершить работу».

Ответы, вероятно, более или менее одинаковы на практике, но при сравнительном тестировании вы должны попытаться сузить его, чтобы сопоставить интересующий вас интерес с минимальным внешним шумом.

Почему бы вам просто не набросить таймер на вызовы pthread_create / forkIO, потому что это то, что вы хотите измерить?

Вас не интересует, сколько времени потребуется для запуска вашей программы, так что не рассчитывайте это время. Вас не интересует, сколько времени потребуется, чтобы присоединиться к темам, так что не рассчитывайте время.

0 голосов
/ 15 февраля 2012

В зависимости от количества потоков, pthread_create() может прекратить создание потоков в какой-то момент; на это следует обратить внимание при бенчмаркинге.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...