<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Sep 30, 2013 at 12:14 PM, Mark Abraham <span dir="ltr">&lt;<a href="mailto:mark.j.abraham@gmail.com" target="_blank">mark.j.abraham@gmail.com</a>&gt;</span> wrote:<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im"><p dir="ltr">
On Sep 29, 2013 10:32 AM, &quot;Erik Lindahl&quot; &lt;<a href="mailto:erik.lindahl@scilifelab.se" target="_blank">erik.lindahl@scilifelab.se</a>&gt; wrote:<br>I can see three possible division levels: mdrun vs tools, md-loop vs rest, hardware-tuned inner loops vs rest. The third is by far the easiest to do.<br>
</p></div>
<p dir="ltr">Cray still requires static linking, and BlueGene/Q encourages it, so I think it is important that the implementation does not require dynamic linking in the cases where portability of the binary is immaterial.</p>
</blockquote><div style>It should be easy enough to do this. At most, it requires an #ifdef per dlsym() call (for static linking or for a single-architecture library, don&#39;t call dlsym() but instead just forward the call to the actual implementation in the same library/binary). <br>
</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">

<p dir="ltr">&gt; 1) Decide on what level we want the interface between library and executables, and keep this interface _really_ small (in the sense that we want to resolve as few symbols as possible).<br>
&gt; 2) Since we will have to compile the high-level binaries with generic compiler flags, any code that is performance-sensitive should go in the architecture-specific optimized library.</p>
</div><p dir="ltr">I think the third option I give above is the most achievable. I do not know whether the dynamic function calls incur overhead per call, or whether that can be mitigated by the helper object Teemu suggested, but he sounds right (as usual). I hope the libraries would share the same address space. Since we anyway plan for tasks to wrap function calls, the implementations converge.</p>
</blockquote><div style>There shouldn&#39;t be any significant overhead (except for the normal overhead from calling through a function pointer and position-independent code in general). Shared libraries get loaded into the same process, so I think they work exactly as if they were linked directly, except that the dynamic loader does not help with symbol resolution beyond providing dlsym().</div>
<div style><br></div><div style>The most important thing to consider on the high level is whether we can/want to allow the dynamically loaded optimized library (libgromacs_opt) to depend on code from the main library (libgromacs). If we push the split to a very high level, it&#39;s difficult to keep such dependencies out without moving all the code into the optimized library. I don&#39;t know if such a semi-circular dependency is a problem for some dynamic loaders, but technically it should not be a big problem (during compilation, there is no such dependency). It&#39;s also possible to break such dependencies by either splitting the shared parts into a yet another library, or by dependency injection (so that libgromacs injects implementation of interfaces for all the shared functionality into libgromacs_opt), but that may be more complex than what we want to make it...</div>
<div style><br></div><div style>Best regards,</div><div style>Teemu</div></div></div></div>