将Haskell线程与内核线程进行比较 - 我的基准是否可行? [英] Comparing Haskell threads to kernel threads - is my benchmark viable?

查看:130
本文介绍了将Haskell线程与内核线程进行比较 - 我的基准是否可行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个实际上是为了我的大学项目。在我的文章中,我需要得到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 *线程;
pthread_attr_t pthread_custom_attr;

如果(argc!= 2)
{
printf(用法:%sn \ n其中n是线程数量\ n,argv [0] );
返回1;
}

n = atoi(argv [1]);

threads =(pthread_t *)malloc(n * sizeof(* threads));
pthread_attr_init(& pthread_custom_attr); (i = 0; i< n; i ++)
{
pthread_create(& threads [i],& pthread_custom_attr,thread_main,(void *)(0)的

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





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

以及Haskell程序:

 模块Main(main)其中

import System.IO.Unsafe
导入系统
导入Control.Concurrent
import Control.Exception

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

waitForChildren :: IO()
waitForChildren = do
cs< - takeMVar children
case $ s
[] - > return()
m:ms - > do
putMVar children ms
takeMVar m
waitForChildren
$ b $ 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)并使用时间测量其运行时间 - f%e ,然后取运行时间的算术平均值。它表明创建Haskell线程的速度要快一个数量级。



现在,我的问题是:这是一个正确的基准吗?或者是否有一些因素需要我考虑以获得准确的结果?

谢谢

解决方案

你的基准可能会让你得到你想要的结果,但是有很多噪音。你所测量的不是创建一个线程需要多长时间,而是启动和运行创建多个线程的程序需要多长时间,然后等待它们在终止之前返回。



在实践中,答案可能大致相同,但在进行基准测试时,您应该尝试缩小范围,以便对您感兴趣的基准进行基准测试尽可能少的外部噪音。



你为什么不简单地在 pthread_create / forkIO 调用,因为它们是你想要衡量的内容?



你不需要花多长时间启动你的程序,所以不要这样做。您对后来加入线程需要多长时间并不感兴趣,所以请不要这么做。


This one is actually for my university project. In my essay, I need to inlcude evidence that Haskell threads are faster to create than plain kernel threads. I know that it's better to refer to some research paper, but the point is that I have to do the benchmarking myself.

Here is what I've come up with. I've written two programs, in C (using pthreads) and Haskell, which create many threads, but those threads do absolutely nothing. I need to measure only the speed of creating a thread.

Here's the source code for the C program:

#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;
}

and for the Haskell program:

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

Now, what I do is I run each program with the same argument (e.g. 10000) and measure their running time with time -f%e, then take the arithmetic mean of the running times. It shows that creating Haskell threads in an order of magnitude faster.

Now, my question is: is this a correct benchmark? or is there some factor that I need to take into account to get accurate results?

Thanks

解决方案

Your benchmarks are probably getting you the result you want, but there's an awful lot of noise. What you're measuring is not "how long does it take to create a thread", but "how long does it take to launch and run a program which creates a number of threads, and then waits for them to return before terminating".

The answers are probably more or less the same in practice, but when benchmarking, you should try to narrow it down so you benchmark that which you're interested in, with as little external noise as possible.

Why don't you simply slap a timer around the pthread_create/forkIO calls, since they're what you want to measure?

You're not interested in how long it takes to launch your program, so don't time that. You're not interested in how long it takes to join the threads afterwards, so don't time that.

这篇关于将Haskell线程与内核线程进行比较 - 我的基准是否可行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆