<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
		>
<channel>
	<title>Comments on: Concurrency and Foreign Functions in the Glasgow Haskell Compiler</title>
	<atom:link href="http://blog.melding-monads.com/2011/10/24/concurrency-and-foreign-functions-in-the-glasgow-haskell-compiler/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.melding-monads.com/2011/10/24/concurrency-and-foreign-functions-in-the-glasgow-haskell-compiler/</link>
	<description>Math, Computer Science,  and Education</description>
	<lastBuildDate>Wed, 08 May 2013 14:59:04 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
	<item>
		<title>By: lpsmith</title>
		<link>http://blog.melding-monads.com/2011/10/24/concurrency-and-foreign-functions-in-the-glasgow-haskell-compiler/#comment-235</link>
		<dc:creator><![CDATA[lpsmith]]></dc:creator>
		<pubDate>Tue, 26 Jun 2012 14:13:29 +0000</pubDate>
		<guid isPermaLink="false">http://blog.melding-monads.com/?p=359#comment-235</guid>
		<description><![CDATA[Ok,  I have confirmed that that you are absolutely correct in that Haskell threads are assigned a capability,  and that those threads will not be rescheduled  on a different capability during an unsafe FFI call.  So thus,  in effect,  an unsafe call blocks all the Haskell threads on the capaibility that it is blocking.    Thanks for the clarification!]]></description>
		<content:encoded><![CDATA[<p>Ok,  I have confirmed that that you are absolutely correct in that Haskell threads are assigned a capability,  and that those threads will not be rescheduled  on a different capability during an unsafe FFI call.  So thus,  in effect,  an unsafe call blocks all the Haskell threads on the capaibility that it is blocking.    Thanks for the clarification!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Sönke Hahn</title>
		<link>http://blog.melding-monads.com/2011/10/24/concurrency-and-foreign-functions-in-the-glasgow-haskell-compiler/#comment-143</link>
		<dc:creator><![CDATA[Sönke Hahn]]></dc:creator>
		<pubDate>Thu, 27 Oct 2011 14:34:50 +0000</pubDate>
		<guid isPermaLink="false">http://blog.melding-monads.com/?p=359#comment-143</guid>
		<description><![CDATA[I see. Thanks!]]></description>
		<content:encoded><![CDATA[<p>I see. Thanks!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: lpsmith</title>
		<link>http://blog.melding-monads.com/2011/10/24/concurrency-and-foreign-functions-in-the-glasgow-haskell-compiler/#comment-142</link>
		<dc:creator><![CDATA[lpsmith]]></dc:creator>
		<pubDate>Thu, 27 Oct 2011 00:37:14 +0000</pubDate>
		<guid isPermaLink="false">http://blog.melding-monads.com/?p=359#comment-142</guid>
		<description><![CDATA[Judging from &lt;a href=&quot;http://haskell.org/ghc/docs/&quot; rel=&quot;nofollow&quot;&gt;old GHC User Guides&lt;/a&gt;, it looks like it was introduced in GHC 6.6 circa 2007.   It looks like GHC 6.4 had a different kind of support for parallelism,  though it&#039;s no longer supported and I don&#039;t know much about it.]]></description>
		<content:encoded><![CDATA[<p>Judging from <a href="http://haskell.org/ghc/docs/" rel="nofollow">old GHC User Guides</a>, it looks like it was introduced in GHC 6.6 circa 2007.   It looks like GHC 6.4 had a different kind of support for parallelism,  though it&#8217;s no longer supported and I don&#8217;t know much about it.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Sönke Hahn</title>
		<link>http://blog.melding-monads.com/2011/10/24/concurrency-and-foreign-functions-in-the-glasgow-haskell-compiler/#comment-141</link>
		<dc:creator><![CDATA[Sönke Hahn]]></dc:creator>
		<pubDate>Wed, 26 Oct 2011 19:26:03 +0000</pubDate>
		<guid isPermaLink="false">http://blog.melding-monads.com/?p=359#comment-141</guid>
		<description><![CDATA[Do you know, when GHC started to support more than one capability? It&#039;s kind of hard to track that down manually.]]></description>
		<content:encoded><![CDATA[<p>Do you know, when GHC started to support more than one capability? It&#8217;s kind of hard to track that down manually.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: almkglor</title>
		<link>http://blog.melding-monads.com/2011/10/24/concurrency-and-foreign-functions-in-the-glasgow-haskell-compiler/#comment-140</link>
		<dc:creator><![CDATA[almkglor]]></dc:creator>
		<pubDate>Wed, 26 Oct 2011 09:56:52 +0000</pubDate>
		<guid isPermaLink="false">http://blog.melding-monads.com/?p=359#comment-140</guid>
		<description><![CDATA[&gt;You do have to save more state though, because (among other things?) you have to ensure that the garbage collector will find everything if the foreign code calls back into Haskell and triggers a GC.

AFAIK it&#039;s really very very simple: a capability is just a glorified mutex lock.  When you perform a safe FFI call, the Haskell code marshals Int&#039;s, etc. into the HsInt etc. C equivalents, then releases the capability (the mutex lock).  If there are no other worker threads, it launches another worker thread.  Then it performs the FFI call.

Any return to Haskell code (either via the FFI C-to-Haskell, or a return from the safe FFI call) then attempts to lock the capability (mutex).  The OS thread blocks until the capability (mutex) is unlocked by whoever got it.]]></description>
		<content:encoded><![CDATA[<p>&gt;You do have to save more state though, because (among other things?) you have to ensure that the garbage collector will find everything if the foreign code calls back into Haskell and triggers a GC.</p>
<p>AFAIK it&#8217;s really very very simple: a capability is just a glorified mutex lock.  When you perform a safe FFI call, the Haskell code marshals Int&#8217;s, etc. into the HsInt etc. C equivalents, then releases the capability (the mutex lock).  If there are no other worker threads, it launches another worker thread.  Then it performs the FFI call.</p>
<p>Any return to Haskell code (either via the FFI C-to-Haskell, or a return from the safe FFI call) then attempts to lock the capability (mutex).  The OS thread blocks until the capability (mutex) is unlocked by whoever got it.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: lpsmith</title>
		<link>http://blog.melding-monads.com/2011/10/24/concurrency-and-foreign-functions-in-the-glasgow-haskell-compiler/#comment-139</link>
		<dc:creator><![CDATA[lpsmith]]></dc:creator>
		<pubDate>Wed, 26 Oct 2011 09:28:29 +0000</pubDate>
		<guid isPermaLink="false">http://blog.melding-monads.com/?p=359#comment-139</guid>
		<description><![CDATA[I don&#039;t think that is correct,  but you do bring up an excellent question... how does the scheduler work,  and what are the consequences of blocking a capability?    Of course, I&#039;m pretty sure the answer depends on particular versions of GHC, and is liable to change again in the future.

My understanding is that the entire capability moves to another OS thread,  and I don&#039;t see why that would entail much overhead.  In particular, you don&#039;t have to move individual Haskell threads.   If that were true,  then the cost of a safe call would be linear in the number of Haskell threads, which would be unacceptable.   You do have to save more state though,  because (among other things?) you have to ensure that the garbage collector will find everything if the foreign code calls back into Haskell and triggers a GC.]]></description>
		<content:encoded><![CDATA[<p>I don&#8217;t think that is correct,  but you do bring up an excellent question&#8230; how does the scheduler work,  and what are the consequences of blocking a capability?    Of course, I&#8217;m pretty sure the answer depends on particular versions of GHC, and is liable to change again in the future.</p>
<p>My understanding is that the entire capability moves to another OS thread,  and I don&#8217;t see why that would entail much overhead.  In particular, you don&#8217;t have to move individual Haskell threads.   If that were true,  then the cost of a safe call would be linear in the number of Haskell threads, which would be unacceptable.   You do have to save more state though,  because (among other things?) you have to ensure that the garbage collector will find everything if the foreign code calls back into Haskell and triggers a GC.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: lpsmith</title>
		<link>http://blog.melding-monads.com/2011/10/24/concurrency-and-foreign-functions-in-the-glasgow-haskell-compiler/#comment-135</link>
		<dc:creator><![CDATA[lpsmith]]></dc:creator>
		<pubDate>Wed, 26 Oct 2011 00:41:46 +0000</pubDate>
		<guid isPermaLink="false">http://blog.melding-monads.com/?p=359#comment-135</guid>
		<description><![CDATA[Hmm, I didn&#039;t really consider the consequences of blocking a capability,  so I wasn&#039;t asking the right questions in that regard.   I just sort of tacitly assumed that it wouldn&#039;t block any other Haskell threads, assuming there was another capability that isn&#039;t blocked.  But that isn&#039;t necessarily true, depending on how GHC&#039;s scheduler is implemented.

That issue sounds like another post that is worth writing.  Thanks!

I too have benchmarked safe versus unsafe calls. I used a safe and unsafe binding to a C function that added the two parameters it was passed,  and used &lt;a href=&quot;http://hackage.haskell.org/package/criterion&quot; rel=&quot;nofollow&quot;&gt;criterion&lt;/a&gt;.   There may well be subtleties that this benchmark didn&#039;t reveal,  but that suggested the overhead to be on the order of 7 nanoseconds for an unsafe call or 100 nanoseconds for an safe call on my systems.   So yes,  if the call is going to take more than about a microsecond, then the overhead isn&#039;t that big of a deal... but I&#039;m not sure what the scheduling granularity of Haskell threads is supposed to approximate, either.   I believe that&#039;s not time based, but rather a counter that counts down as you pass through yield points,  so I believe the granularity can depend on what you are doing.

Regarding memcpy,  you can determine how much memory it&#039;s going to copy based on the parameters,  so you could have a simple Haskell wrapper that executes either a safe or unsafe call accordingly.   You could even have GHC inline the wrapper and get rid of the branch in the case of constants.]]></description>
		<content:encoded><![CDATA[<p>Hmm, I didn&#8217;t really consider the consequences of blocking a capability,  so I wasn&#8217;t asking the right questions in that regard.   I just sort of tacitly assumed that it wouldn&#8217;t block any other Haskell threads, assuming there was another capability that isn&#8217;t blocked.  But that isn&#8217;t necessarily true, depending on how GHC&#8217;s scheduler is implemented.</p>
<p>That issue sounds like another post that is worth writing.  Thanks!</p>
<p>I too have benchmarked safe versus unsafe calls. I used a safe and unsafe binding to a C function that added the two parameters it was passed,  and used <a href="http://hackage.haskell.org/package/criterion" rel="nofollow">criterion</a>.   There may well be subtleties that this benchmark didn&#8217;t reveal,  but that suggested the overhead to be on the order of 7 nanoseconds for an unsafe call or 100 nanoseconds for an safe call on my systems.   So yes,  if the call is going to take more than about a microsecond, then the overhead isn&#8217;t that big of a deal&#8230; but I&#8217;m not sure what the scheduling granularity of Haskell threads is supposed to approximate, either.   I believe that&#8217;s not time based, but rather a counter that counts down as you pass through yield points,  so I believe the granularity can depend on what you are doing.</p>
<p>Regarding memcpy,  you can determine how much memory it&#8217;s going to copy based on the parameters,  so you could have a simple Haskell wrapper that executes either a safe or unsafe call accordingly.   You could even have GHC inline the wrapper and get rid of the branch in the case of constants.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gábor Lehel</title>
		<link>http://blog.melding-monads.com/2011/10/24/concurrency-and-foreign-functions-in-the-glasgow-haskell-compiler/#comment-138</link>
		<dc:creator><![CDATA[Gábor Lehel]]></dc:creator>
		<pubDate>Tue, 25 Oct 2011 14:07:16 +0000</pubDate>
		<guid isPermaLink="false">http://blog.melding-monads.com/?p=359#comment-138</guid>
		<description><![CDATA[As far as I understand it, moving the other Haskell threads from the capability over to a different one is precisely what a safe call does, and is part of the overhead which unsafe calls avoid. (Or rather, I think it&#039;s the thread making the call which gets moved over and the others stay, but that sounds mostly isomorphic.)

Yield points are whenever allocation happens, but I don&#039;t know anything about it beyond that.

Regarding memcpy, that&#039;s such an obvious solution that I&#039;m somewhat embarrassed I didn&#039;t think of it. Thanks. :)]]></description>
		<content:encoded><![CDATA[<p>As far as I understand it, moving the other Haskell threads from the capability over to a different one is precisely what a safe call does, and is part of the overhead which unsafe calls avoid. (Or rather, I think it&#8217;s the thread making the call which gets moved over and the others stay, but that sounds mostly isomorphic.)</p>
<p>Yield points are whenever allocation happens, but I don&#8217;t know anything about it beyond that.</p>
<p>Regarding memcpy, that&#8217;s such an obvious solution that I&#8217;m somewhat embarrassed I didn&#8217;t think of it. Thanks. :)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gábor Lehel</title>
		<link>http://blog.melding-monads.com/2011/10/24/concurrency-and-foreign-functions-in-the-glasgow-haskell-compiler/#comment-134</link>
		<dc:creator><![CDATA[Gábor Lehel]]></dc:creator>
		<pubDate>Mon, 24 Oct 2011 22:06:02 +0000</pubDate>
		<guid isPermaLink="false">http://blog.melding-monads.com/?p=359#comment-134</guid>
		<description><![CDATA[Just to make it clearer (for anyone reading) what blocking a capability means: it means *all* Haskell threads scheduled on that capability are blocked for the duration of the call, not just the one making the foreign call. If the function completes quickly (or if there aren&#039;t any other Haskell threads scheduled on the capability, e.g. if M isn&#039;t (much) larger than N), it won&#039;t matter. Otherwise, it might.

This happens because unsafe calls are basically just direct C function calls. Safe calls are that plus various book-keeping and thread juggling.

A difficulty is that how long a call takes frequently depends on its what its arguments are (or on other external state). memcpy could copy a byte, or a gigabyte. Is there any good solution to this other than importing both a safe and an unsafe version and leaving the choice to the client? If you use the function internally, you could end up needing to provide two versions of every function which uses it (per each such foreign import), so this doesn&#039;t seem really tractable in the general case... I guess the only safe thing to do is to leave some performance on the table and always make safe calls when in doubt, and to only make unsafe ones when you can be sure they won&#039;t block for too long.

Remi Turk was kind enough to do some benchmarks of safe calls vs. unsafe calls vs. his cinvoke library bindings a while back, with both the threaded and non-threaded runtimes:

http://www.haskell.org/pipermail/haskell-cafe/2011-March/090029.html
http://www.haskell.org/pipermail/haskell-cafe/2011-March/090083.html

The overhead of safe calls seems to be quite low for (presumably most) non-synthetic use cases.]]></description>
		<content:encoded><![CDATA[<p>Just to make it clearer (for anyone reading) what blocking a capability means: it means *all* Haskell threads scheduled on that capability are blocked for the duration of the call, not just the one making the foreign call. If the function completes quickly (or if there aren&#8217;t any other Haskell threads scheduled on the capability, e.g. if M isn&#8217;t (much) larger than N), it won&#8217;t matter. Otherwise, it might.</p>
<p>This happens because unsafe calls are basically just direct C function calls. Safe calls are that plus various book-keeping and thread juggling.</p>
<p>A difficulty is that how long a call takes frequently depends on its what its arguments are (or on other external state). memcpy could copy a byte, or a gigabyte. Is there any good solution to this other than importing both a safe and an unsafe version and leaving the choice to the client? If you use the function internally, you could end up needing to provide two versions of every function which uses it (per each such foreign import), so this doesn&#8217;t seem really tractable in the general case&#8230; I guess the only safe thing to do is to leave some performance on the table and always make safe calls when in doubt, and to only make unsafe ones when you can be sure they won&#8217;t block for too long.</p>
<p>Remi Turk was kind enough to do some benchmarks of safe calls vs. unsafe calls vs. his cinvoke library bindings a while back, with both the threaded and non-threaded runtimes:</p>
<p><a href="http://www.haskell.org/pipermail/haskell-cafe/2011-March/090029.html" rel="nofollow">http://www.haskell.org/pipermail/haskell-cafe/2011-March/090029.html</a><br />
<a href="http://www.haskell.org/pipermail/haskell-cafe/2011-March/090083.html" rel="nofollow">http://www.haskell.org/pipermail/haskell-cafe/2011-March/090083.html</a></p>
<p>The overhead of safe calls seems to be quite low for (presumably most) non-synthetic use cases.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
