<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re:  transforming single-threaded allocators... in Intel® Moderncode for Parallel Architectures</title>
    <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872565#M3012</link>
    <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="margin-top: 5px; width: 100%;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/347331"&gt;Dmitriy V'jukov&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;I think that TBB's approach has some advantages over automatically turning purely single-threaded allocator into multi-threaded. Consider points 1 and 2.&lt;/P&gt;
&lt;P&gt;Though it's beyond question that your automatic approach is faaaaaaaaar better than just protecting single-threaded allocator with single mutex (or with fine-grained mutexes) - the thing we currently see in many allocators.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;DIV&gt;Here are some of my current thoughts:&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;A href="http://groups.google.com/group/comp.programming.threads/browse_frm/thread/1689f58f066a5995"&gt;http://groups.google.com/group/comp.programming.threads/browse_frm/thread/1689f58f066a5995&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;I seems like Intel's per-thread allocator instances areprobably aheck of a lot more optimized than Windows Heap API w/ `HEAP_NO_SERIALIZE' flag. I also like how they move super-blocks out of threads and defer to global allocator onlarge allocations. However, I do find it a little strange that they don't use XCHG for reclaiming remote deallocations.&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;As for my "generic" algorithm, well, with Windows Heaps I simply cannot get it to beat my region allocator:&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;A href="http://webpages.charter.net/appcore/vzoom/malloc/sergey_vzmem_thread.html"&gt;http://webpages.charter.net/appcore/vzoom/malloc/sergey_vzmem_thread.html&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;Also, I can't get it to beat the allocator in the current vZOOM commercial package. I guess its good in a sense because it can definitely transform basically any single-threaded allocation technique into a distributed thread-safe entity. IMVHO, its a good algorithm to study...&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;Perhaps, I am going to try some optimizations... Such as limiting the size of per-thread heaps by utilizing the max_size parameter in the HeapCreate function. Perhaps mess around with a caching algorithm on remote frees. When `HeapAlloc()' fails, it defers to a global low-frag heap. However, I don't know how much this is going to buy me because it seems like calling into `HeapAlloc()/Free()' is an expensive operation no matter if `HEAP_NO_SERIALIZE' is set or not.&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;Although, the "generic" nature of the current algorithm cannot take advantage of header-less blocks. This has major overhead on a per-allocation basis. Since the algorithm does not know anything about the underlying per-thread allocators, well, it basically has to have a nasty header. I am not sure how to overcome this without forcing a deeper interaction between the algorithm and the allocators its managing.&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;BTW, do you know off hand if TBB allocator uses header-less blocks?&lt;BR /&gt;&lt;/DIV&gt;</description>
    <pubDate>Wed, 08 Oct 2008 10:01:28 GMT</pubDate>
    <dc:creator>Chris_M__Thomasson</dc:creator>
    <dc:date>2008-10-08T10:01:28Z</dc:date>
    <item>
      <title>transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872559#M3006</link>
      <description>&lt;P&gt;My name is Chris M. Thomasson and I have developed a non-blocking algorithm that allows one to transform an inherently single-threaded memory allocator into a scaleable multi-threaded allocator. This invention allows a programmer to just create an allocator algorithm without worrying about any multi-threading issues. Once your done with your single-threaded allocator, well, when you apply my non-blocking algorithm, and PRESTO! Its now a scaleable multi-threaded allocator! Is that cool or what?&lt;/P&gt;
&lt;P&gt;Okay, here is an initial proof of concept, I have transformed the Windows Heap object created with the HEAP_NO_SERIALIZE flag. This flag disables the internal lock used by the heap, which makes it a heck of a lot more efficient. However, since the heap is no longer serialized, one cannot use it in a multi-threaded application as a general allocator; until now... The algorithm I created is fairly simple; basically, it goes like this:&lt;BR /&gt;___________________________________________________________________________&lt;BR /&gt;I create thread local user allocator in every thread.&lt;/P&gt;
&lt;P&gt;Alloc request is forwarded to this thread-local user allocator directly.&lt;/P&gt;
&lt;P&gt;If free request goes from thread that allocate block, then free request is forwarded to this thread-local user allocator.&lt;/P&gt;
&lt;P&gt;If free request goes from another thread, then you accumulate this block in per-thread stack-based freelist.&lt;/P&gt;
&lt;P&gt;Blocks from this freelist are actually freed in batches when thread allocates/deallocates another block.&lt;BR /&gt;___________________________________________________________________________&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;I mentioned this algorithm a while back:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://groups.google.com/group/comp.programming.threads/browse_frm/thread/eb87f9cb2cb62d84"&gt;http://groups.google.com/group/comp.programming.threads/browse_frm/thread/eb87f9cb2cb62d84&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;Well, I have released a pre-alpha version of it which demonstrates how to transform the Windows Heap object under GPL license; the example source-code can be found here:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://webpages.charter.net/appcore/vzoom/malloc/vzmalloc_win_v000_c.html"&gt;http://webpages.charter.net/appcore/vzoom/malloc/vzmalloc_win_v000_c.html&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;Can you please run the test as-is, which uses stock malloc impl, and record the output... Then uncomment the following line:&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;#define USE_MEM_ALLOC&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;which engages my algorithm; run the test again; and post the differences in timings between the two. I think you will be fairly surprised at the performance enhancement. The lock in the Windows Heap object that `malloc' is based on severely damages its scalability when used in a multi-threaded environment. When `USE_MEM_ALLOC' is defined, ALL of the locking is removed and the heaps are created on a per-thread basis. This distribution and clever support algorithm I invented allows for the Windows Heap to scale quite nicely indeed.&lt;/P&gt;
&lt;P&gt;I am going to tweak the algorithm such that one could plug in different allocators on a per-thread basis! In other words, thread A can use a different allocation algorithm than thread B, and so on. My algorithm actually supports this. I think the possibilities are truly amazing. It even allows thread A to allocate and free in thread B even though they use completely different allocation algorithm. That's pretty darn cool. Some may think its even impossible; its not!&lt;/P&gt;
&lt;P&gt;BTW, I am thinking that this algorithm might be able to be used to transform other single-threaded things besides allocators... Humm, need to think some more on that.&lt;/P&gt;
&lt;P&gt;P.S.&lt;/P&gt;
&lt;P&gt;The test portion of the code uses the pthread-win32 library which can be downloaded from here:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://sourceware.org/pthreads-win32"&gt;http://sourceware.org/pthreads-win32&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;I am thinking of removing dependence on it and just use pure Windows primitives.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Any thoughts?&lt;/P&gt;</description>
      <pubDate>Wed, 08 Oct 2008 04:34:02 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872559#M3006</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2008-10-08T04:34:02Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872560#M3007</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;I posted the WRONG VERSION! I did not include the reclaim threshold experimental feature I am playing around with. Also, there was a bug in the following function `mem_thread_sys_reclaim()'. Here was the original code:&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;&lt;BR /&gt;LONG&lt;BR /&gt;mem_thread_sys_reclaim(&lt;BR /&gt;union mem_block* const reset&lt;BR /&gt;) {&lt;BR /&gt; LONG count = 0;&lt;BR /&gt; union mem_block* mblk = XCHG(&amp;amp;g_mem_tls-&amp;gt;rfree, reset);&lt;BR /&gt; while (mblk) {&lt;BR /&gt; union mem_block* const next = mblk-&amp;gt;next;&lt;BR /&gt; if (! HeapFree(g_mem_tls-&amp;gt;heap, HEAP_NO_SERIALIZE, mblk)) {&lt;BR /&gt; assert(0); abort();&lt;BR /&gt; }&lt;BR /&gt; ++count;&lt;BR /&gt; mblk = next;&lt;BR /&gt; }&lt;BR /&gt; if (! reset) {&lt;BR /&gt; g_mem_tls-&amp;gt;refs += count;&lt;BR /&gt; }&lt;BR /&gt; return count;&lt;BR /&gt;}&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;&lt;BR /&gt;Can you spot the bug? Well, IMVHO, its kind of easy... See, the reclaim function is suppose to free the blocks that have been deferred by remote threads... Well, a free is suppose to actually decrement the owner thread reference count... I was incrementing it! OUCH!&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;;^(...&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;Anyway, its fixed on the web-site. I needed to change the code:&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt; if (! reset) {&lt;BR /&gt; g_mem_tls-&amp;gt;refs += count;&lt;BR /&gt; }&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;&lt;BR /&gt;to:&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt; if (! reset) {&lt;BR /&gt; g_mem_tls-&amp;gt;refs -= count;&lt;BR /&gt; }&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;So, you should re-download the source-code! Sorry for any trouble.&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;&lt;BR /&gt;&lt;A href="http://webpages.charter.net/appcore/vzoom/malloc/vzmalloc_win_v000_c.html"&gt;http://webpages.charter.net/appcore/vzoom/malloc/vzmalloc_win_v000_c.html&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;&lt;BR /&gt;Anyway, I am not sure how the reclaim threshold feature is going to effect performance. Humm... Need to think about this.&lt;/DIV&gt;</description>
      <pubDate>Wed, 08 Oct 2008 05:21:03 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872560#M3007</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2008-10-08T05:21:03Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872561#M3008</link>
      <description>&lt;DIV style="margin:0px;"&gt;BTW, in case anybody is interested, here is the first time I made the base non-blocking algorithm itself public:&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;&lt;A href="http://groups.google.com/group/comp.programming.threads/browse_frm/thread/8245f4b48591fc69"&gt;http://groups.google.com/group/comp.programming.threads/browse_frm/thread/8245f4b48591fc69&lt;/A&gt;&lt;/DIV&gt;</description>
      <pubDate>Wed, 08 Oct 2008 05:23:35 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872561#M3008</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2008-10-08T05:23:35Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872562#M3009</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;I improved the test application; the web-page is updated. See, before, it was actually calling `my_malloc/free' functions under the protection of the test mutex. Well, that's no good. So, I moved them outside of the critical-region. Now, it would be an interesting experiment to run both versions of the test. One with the allocation functions in the critical-section, and one without. On my end, my algorithm beats normal malloc/free in either occasion, but really whips them when they are not protected by the mutex. Can you please post some numbers? I am curious to see how horrible stock malloc/free actually are!&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;;^D&lt;/DIV&gt;</description>
      <pubDate>Wed, 08 Oct 2008 05:42:18 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872562#M3009</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2008-10-08T05:42:18Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872563#M3010</link>
      <description>&lt;P&gt;Intel TBB's scalable malloc uses the same technique.&lt;/P&gt;
&lt;P&gt;The interesting things about TBB's scalable malloc:&lt;/P&gt;
&lt;P&gt;- for large objects (currently bigger than 8064 bytes) global allocator is used (plain malloc, or mmap - chosen by define)&lt;/P&gt;
&lt;P&gt;- there is also global cache of superfluous memory superblocks, i.e. if thread has too many superblocks it moves superblocks to global cache&lt;/P&gt;
&lt;P&gt;- there is no caching, i.e. if thread constantly frees remote memory it will constantly execute atomic ops (very bad in some scenarios - producer/consumer)&lt;/P&gt;
&lt;P&gt;- inter-thread queue organized as lock-free stack (IBM freelist), or as mutex-protected stack&lt;/P&gt;
&lt;P&gt;- thread grabs lock-free stack with CAS, not with XCHG&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 08 Oct 2008 08:14:47 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872563#M3010</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2008-10-08T08:14:47Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872564#M3011</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/347331"&gt;Dmitriy V'jukov&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;P&gt;Intel TBB's scalable malloc uses the same technique.&lt;/P&gt;
&lt;P&gt;The interesting things about TBB's scalable malloc:&lt;/P&gt;
&lt;P&gt;- for large objects (currently bigger than 8064 bytes) global allocator is used (plain malloc, or mmap - chosen by define)&lt;/P&gt;
&lt;P&gt;- there is also global cache of superfluous memory superblocks, i.e. if thread has too many superblocks it moves superblocks to global cache&lt;/P&gt;
&lt;P&gt;- there is no caching, i.e. if thread constantly frees remote memory it will constantly execute atomic ops (very bad in some scenarios - producer/consumer)&lt;/P&gt;
&lt;P&gt;- inter-thread queue organized as lock-free stack (IBM freelist), or as mutex-protected stack&lt;/P&gt;
&lt;P&gt;- thread grabs lock-free stack with CAS, not with XCHG&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;I think that TBB's approach has some advantages over automatically turning purely single-threaded allocator into multi-threaded. Consider points 1 and 2.&lt;/P&gt;
&lt;P&gt;Though it's beyond question that your automatic approach is faaaaaaaaar better than just protecting single-threaded allocator with single mutex (or with fine-grained mutexes) - the thing we currently see in many allocators.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 08 Oct 2008 08:20:27 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872564#M3011</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2008-10-08T08:20:27Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872565#M3012</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="margin-top: 5px; width: 100%;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/347331"&gt;Dmitriy V'jukov&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;I think that TBB's approach has some advantages over automatically turning purely single-threaded allocator into multi-threaded. Consider points 1 and 2.&lt;/P&gt;
&lt;P&gt;Though it's beyond question that your automatic approach is faaaaaaaaar better than just protecting single-threaded allocator with single mutex (or with fine-grained mutexes) - the thing we currently see in many allocators.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;DIV&gt;Here are some of my current thoughts:&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;A href="http://groups.google.com/group/comp.programming.threads/browse_frm/thread/1689f58f066a5995"&gt;http://groups.google.com/group/comp.programming.threads/browse_frm/thread/1689f58f066a5995&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;I seems like Intel's per-thread allocator instances areprobably aheck of a lot more optimized than Windows Heap API w/ `HEAP_NO_SERIALIZE' flag. I also like how they move super-blocks out of threads and defer to global allocator onlarge allocations. However, I do find it a little strange that they don't use XCHG for reclaiming remote deallocations.&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;As for my "generic" algorithm, well, with Windows Heaps I simply cannot get it to beat my region allocator:&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;A href="http://webpages.charter.net/appcore/vzoom/malloc/sergey_vzmem_thread.html"&gt;http://webpages.charter.net/appcore/vzoom/malloc/sergey_vzmem_thread.html&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;Also, I can't get it to beat the allocator in the current vZOOM commercial package. I guess its good in a sense because it can definitely transform basically any single-threaded allocation technique into a distributed thread-safe entity. IMVHO, its a good algorithm to study...&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;Perhaps, I am going to try some optimizations... Such as limiting the size of per-thread heaps by utilizing the max_size parameter in the HeapCreate function. Perhaps mess around with a caching algorithm on remote frees. When `HeapAlloc()' fails, it defers to a global low-frag heap. However, I don't know how much this is going to buy me because it seems like calling into `HeapAlloc()/Free()' is an expensive operation no matter if `HEAP_NO_SERIALIZE' is set or not.&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;Although, the "generic" nature of the current algorithm cannot take advantage of header-less blocks. This has major overhead on a per-allocation basis. Since the algorithm does not know anything about the underlying per-thread allocators, well, it basically has to have a nasty header. I am not sure how to overcome this without forcing a deeper interaction between the algorithm and the allocators its managing.&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;BTW, do you know off hand if TBB allocator uses header-less blocks?&lt;BR /&gt;&lt;/DIV&gt;</description>
      <pubDate>Wed, 08 Oct 2008 10:01:28 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872565#M3012</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2008-10-08T10:01:28Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872566#M3013</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/6002"&gt;lockfree&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;DIV&gt;Although, the "generic" nature of the current algorithm cannot take advantage of header-less blocks. This has major overhead on a per-allocation basis. Since the algorithm does not know anything about the underlying per-thread allocators, well, it basically has to have a nasty header. I am not sure how to overcome this without forcing a deeper interaction between the algorithm and the allocators its managing.&lt;/DIV&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;Indeed. Interaction yields fruits.&lt;/P&gt;
&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/6002"&gt;lockfree&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;BTW, do you know off hand if TBB allocator uses header-less blocks?&lt;BR /&gt;&lt;/DIV&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P style="padding-left: 30px;"&gt;extern "C" void scalable_free (void *object) {&lt;BR /&gt; Block *block;&lt;BR /&gt; ThreadId myTid;&lt;BR /&gt; FreeObject *objectToFree;&lt;BR /&gt;&lt;BR /&gt; if (!object) {&lt;BR /&gt; return;&lt;BR /&gt; }&lt;BR /&gt;&lt;BR /&gt; if (isLargeObject(object)) {&lt;BR /&gt; freeLargeObject(object);&lt;BR /&gt; return;&lt;BR /&gt; }&lt;BR /&gt;&lt;BR /&gt; objectToFree = (FreeObject *)object;&lt;BR /&gt;&lt;BR /&gt; myTid = getThreadId();&lt;BR /&gt;&lt;BR /&gt; block = (Block *) ((uintptr_t)object &amp;amp; ~(blockSize - 1));/* mask low bits to get the block */&lt;BR /&gt; MALLOC_ASSERT (block-&amp;gt;allocatedCount, ASSERT_TEXT);&lt;BR /&gt;&lt;BR /&gt; if (myTid == block-&amp;gt;owner) {&lt;/P&gt;
&lt;P style="padding-left: 30px;"&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 08 Oct 2008 10:23:14 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872566#M3013</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2008-10-08T10:23:14Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872567#M3014</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="margin-top: 5px; width: 100%;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/347331"&gt;Dmitriy V'jukov&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;P&gt;Indeed. Interaction yields fruits.&lt;/P&gt;
&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="margin-top: 5px; width: 100%;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/6002"&gt;lockfree&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;DIV&gt;BTW, do you know off hand if TBB allocator uses header-less blocks?&lt;BR /&gt;&lt;/DIV&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P style="padding-left: 30px;"&gt;extern "C" void scalable_free (void *object) {&lt;BR /&gt;Block *block;&lt;BR /&gt;ThreadId myTid;&lt;BR /&gt;FreeObject *objectToFree;&lt;BR /&gt;&lt;BR /&gt;if (!object) {&lt;BR /&gt;return;&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;if (isLargeObject(object)) {&lt;BR /&gt;freeLargeObject(object);&lt;BR /&gt;return;&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;objectToFree = (FreeObject *)object;&lt;BR /&gt;&lt;BR /&gt;myTid = getThreadId();&lt;BR /&gt;&lt;BR /&gt;block = (Block *) ((uintptr_t)object &amp;amp; ~(blockSize - 1));/* mask low bits to get the block */&lt;BR /&gt;MALLOC_ASSERT (block-&amp;gt;allocatedCount, ASSERT_TEXT);&lt;BR /&gt;&lt;BR /&gt;if (myTid == block-&amp;gt;owner) {&lt;/P&gt;
&lt;P style="padding-left: 30px;"&gt;&lt;/P&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;DIV&gt;That will definitely do it. I use the same technique in vZOOM and the region allocator. Its basically the only way to accomplish it efficiently. I take it that their `Block' object is a slab of fixed sized objects, and that don't have support for `realloc()' right? I mean they could do it for sure, if they used copying...&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;As for remote deallocations, well, I am thinking of a way to get it done, but its going to be a little tricky. This is because a blocks from a slab could be scattered across multiple threads instead of always being directed to the owner. Interesting problem indeed!&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;;^D&lt;BR /&gt;&lt;/DIV&gt;</description>
      <pubDate>Wed, 08 Oct 2008 11:59:59 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872567#M3014</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2008-10-08T11:59:59Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872568#M3015</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/6002"&gt;lockfree&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;DIV&gt;I take it that their `Block' object is a slab of fixed sized objects, and that don't have support for `realloc()' right? I mean they could do it for sure, if they used copying...&lt;/DIV&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;Yes, Block is fixed-size slab allocator.&lt;/P&gt;
&lt;P&gt;If requested via realloc size is smaller than current size, then no copying. This is true and for small fixed-size objects and for big objects.&lt;/P&gt;
&lt;P&gt;If requested via realloc size is bigger than current size, then, yes, new block is allocated and memory copied.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/6002"&gt;lockfree&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;As for remote deallocations, well, I am thinking of a way to get it done, but its going to be a little tricky. This is because a blocks from a slab could be scattered across multiple threads instead of always being directed to the owner. Interesting problem indeed!&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;I don't get you. What do you mean by "&lt;EM&gt;&lt;EM&gt;blocks from a slab could be scattered across multiple threads instead of always being directed to the owner&lt;/EM&gt;&lt;/EM&gt;"?&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 08 Oct 2008 12:29:49 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872568#M3015</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2008-10-08T12:29:49Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872569#M3016</link>
      <description>&lt;P&gt;Another interesting moment about TBB's scalable malloc - how it determines large objects. This is exactly what we discussed several days ago:&lt;BR /&gt;&lt;BR /&gt;&lt;A href="http://groups.google.com/group/comp.programming.threads/browse_frm/thread/eb0cc5c0218b8570" target="_blank"&gt;http://groups.google.com/group/comp.programming.threads/browse_frm/thread/eb0cc5c0218b8570&lt;/A&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt; /* Does this object start on a 16K boundary + the size of a large object header? */&lt;BR /&gt; static inline unsigned int isLargeObject(void *object)&lt;BR /&gt; {&lt;BR /&gt; return ((uintptr_t)object &amp;amp; (blockSize - 1)) == sizeof(LargeObjectHeader);&lt;BR /&gt; }&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;Hmmm... I thinking how this can be improved...&lt;BR /&gt;&lt;BR /&gt;For example, we have 64kb superblocks in slab-allocator. We can not use objects starting at 0kb, 4kb, 8kb, 12kb, ..., 62 kb in slab-allocator. And place big objects exactly at those offsets. So we will have a bit more freedom where we can place big objects.&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 08 Oct 2008 12:43:28 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872569#M3016</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2008-10-08T12:43:28Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872570#M3017</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV style="margin:0px;"&gt;I forget to clarify. I was referring to moment when `realloc()' is invoked from a thread that does not own the slab in which the block resides. AFAICT,this would require creating a new block in calling threads slab, copying the origin block, then pushing the origin block onto its remote owner thread.&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;As for my comment on blocks being scattered, well, I again forget to clarify another important moment. I was thinking of ways to cache blocks in remote threads. Well, when the owner thread dies, there could be multiple threads which have blocks from its slabs cached. Humm...&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;Am I making sense now? Anyway, sorry about that!&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;:^/&lt;/DIV&gt;</description>
      <pubDate>Wed, 08 Oct 2008 12:43:46 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872570#M3017</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2008-10-08T12:43:46Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872571#M3018</link>
      <description>&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;gt;&amp;gt; block = (Block *) ((uintptr_t)object &amp;amp; ~(blockSize - 1));/* mask low bits to get the block */&lt;/P&gt;
&lt;P&gt;I haven't looked at the allocation code in TBB and in particular the definition of Block but...&lt;/P&gt;
&lt;P&gt;The above would requre sizeof(Block) to be a power of 2 (not much of a problem)&lt;BR /&gt;&lt;EM&gt;and&lt;/EM&gt; that the first few bytes object reside &lt;EM&gt;within&lt;/EM&gt; Block. This could introduce problems when (if) alligned allocations are supported and then would require the size of Block to be at least as large as the largest aligned allocation supported.Then consider thatthe alignment requirements of the application are unknown to the author of the allocation routine.&lt;/P&gt;
&lt;P&gt;I would think a better route would be to prepend a locator in front of the returned object pointer (residing within the prepended Block object). This could either bethe Block* itself, or a -byte count from the object pointer to the base of the Block.&lt;/P&gt;
&lt;P&gt;Jim Dempsey&lt;/P&gt;</description>
      <pubDate>Wed, 08 Oct 2008 12:53:11 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872571#M3018</guid>
      <dc:creator>jimdempseyatthecove</dc:creator>
      <dc:date>2008-10-08T12:53:11Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872572#M3019</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/99850"&gt;jimdempseyatthecove&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;P&gt;&amp;gt;&amp;gt; block = (Block *) ((uintptr_t)object &amp;amp; ~(blockSize - 1));/* mask low bits to get the block */&lt;/P&gt;
&lt;P&gt;I haven't looked at the allocation code in TBB and in particular the definition of Block but...&lt;/P&gt;
&lt;P&gt;The above would requre sizeof(Block) to be a power of 2 (not much of a problem)&lt;BR /&gt;&lt;EM&gt;and&lt;/EM&gt; that the first few bytes object reside &lt;EM&gt;within&lt;/EM&gt; Block. This could introduce problems when (if) alligned allocations are supported and then would require the size of Block to be at least as large as the largest aligned allocation supported.Then consider thatthe alignment requirements of the application are unknown to the author of the allocation routine.&lt;/P&gt;
&lt;P&gt;I would think a better route would be to prepend a locator in front of the returned object pointer (residing within the prepended Block object). This could either bethe Block* itself, or a -byte count from the object pointer to the base of the Block.&lt;/P&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;Allocator ALWAYS knows alignment requirements of the platform. I'm not sure what you mean by "alignment requirements of the &lt;STRONG&gt;application&lt;/STRONG&gt;".&lt;/P&gt;
&lt;P&gt;What you are proposing is exactly the thing which developers (and Chris) tried to avoid. Header-prefixed allocations can be too expensive for small objects.&lt;/P&gt;</description>
      <pubDate>Wed, 08 Oct 2008 13:44:17 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872572#M3019</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2008-10-08T13:44:17Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872573#M3020</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="margin-top: 5px; width: 100%;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/347331"&gt;Dmitriy V'jukov&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;P&gt;Another interesting moment about TBB's scalable malloc - how it determines large objects. This is exactly what we discussed several days ago:&lt;BR /&gt;&lt;BR /&gt;&lt;A href="http://groups.google.com/group/comp.programming.threads/browse_frm/thread/eb0cc5c0218b8570" target="_blank"&gt;http://groups.google.com/group/comp.programming.threads/browse_frm/thread/eb0cc5c0218b8570&lt;/A&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;/* Does this object start on a 16K boundary + the size of a large object header? */&lt;BR /&gt;static inline unsigned int isLargeObject(void *object)&lt;BR /&gt;{&lt;BR /&gt;return ((uintptr_t)object &amp;amp; (blockSize - 1)) == sizeof(LargeObjectHeader);&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;Hmmm... I thinking how this can be improved...&lt;BR /&gt;&lt;BR /&gt;For example, we have 64kb superblocks in slab-allocator. We can not use objects starting at 0kb, 4kb, 8kb, 12kb, ..., 62 kb in slab-allocator. And place big objects exactly at those offsets. So we will have a bit more freedom where we can place big objects.&lt;/P&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;DIV&gt;Humm... Very interesting fine-grain approach. I am thinking how to handle allocations that need to span multiple super-blocks. Well, I guess a possible, perhaps naive, approach would be to align them on a boundary that is greater thanthe size of asuper-block. Then one could tell allocations that are over 64k apart from all the others...&lt;/DIV&gt;</description>
      <pubDate>Wed, 08 Oct 2008 13:48:32 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872573#M3020</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2008-10-08T13:48:32Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872574#M3021</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/6002"&gt;lockfree&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;&lt;BR /&gt;
&lt;DIV&gt;As for my comment on blocks being scattered, well, I again forget to clarify another important moment. I was thinking of ways to cache blocks in remote threads. Well, when the owner thread dies, there could be multiple threads which have blocks from its slabs cached. Humm...&lt;/DIV&gt;
&lt;BR /&gt;&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;Do you mean that they can be cached for a way too long (i.e. infinitely)?&lt;/P&gt;
&lt;P&gt;Caching for limited amount of time can not be a problem, because when thread dies there still can be blocks owned by that thread in use.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 08 Oct 2008 13:56:26 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872574#M3021</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2008-10-08T13:56:26Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872575#M3022</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/6002"&gt;lockfree&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;DIV&gt;Humm... Very interesting fine-grain approach. I am thinking how to handle allocations that need to span multiple super-blocks. Well, I guess a possible, perhaps naive, approach would be to align them on a boundary that is greater thanthe size of asuper-block. Then one could tell allocations that are over 64k apart from all the others...&lt;/DIV&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Possibly we have some misunderstanding because of terminology.&lt;/P&gt;
&lt;P&gt;What is the problem to handle objects bigger than superblock? One just have to allocate then via ::malloc. They are big so it must not be a problem. Or they can be allocated directly via mmap()/VirtualAlloc(). This is approach used in TBB's scalable malloc.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 08 Oct 2008 14:04:14 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872575#M3022</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2008-10-08T14:04:14Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872576#M3023</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="margin-top: 5px; width: 100%;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/99850"&gt;jimdempseyatthecove&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;P&gt;&amp;gt;&amp;gt; block = (Block *) ((uintptr_t)object &amp;amp; ~(blockSize - 1));/* mask low bits to get the block */&lt;/P&gt;
&lt;P&gt;I haven't looked at the allocation code in TBB and in particular the definition of Block but...&lt;/P&gt;
&lt;P&gt;The above would requre sizeof(Block) to be a power of 2 (not much of a problem)&lt;BR /&gt;&lt;EM&gt;and&lt;/EM&gt; that the first few bytes object reside &lt;EM&gt;within&lt;/EM&gt; Block. This could introduce problems when (if) alligned allocations are supported and then would require the size of Block to be at least as large as the largest aligned allocation supported.Then consider thatthe alignment requirements of the application are unknown to the author of the allocation routine.&lt;/P&gt;
&lt;P&gt;I would think a better route would be to prepend a locator in front of the returned object pointer (residing within the prepended Block object). This could either bethe Block* itself, or a -byte count from the object pointer to the base of the Block.&lt;/P&gt;
&lt;P&gt;Jim Dempsey&lt;/P&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;DIV&gt;Noblocks within the slab would reside anywhere in the header whatsoever; what makes you think that? Consider this trivial naive simple layout:&lt;/DIV&gt;
&lt;DIV&gt;_________________________________________________________________&lt;/DIV&gt;
&lt;DIV&gt;#define L2_CACHE_LINE 128&lt;/DIV&gt;
&lt;DIV&gt;#define PAGE_SIZE 8192&lt;/DIV&gt;
&lt;DIV&gt;#define BLKBUF_SIZE (PAGE_SIZE - L2_CACHE_LINE)&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;struct header {&lt;/DIV&gt;
&lt;DIV&gt; /* [blah, blah]; */&lt;/DIV&gt;
&lt;DIV&gt;};&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;union header_l2pad {&lt;/DIV&gt;
&lt;DIV&gt; struct header this;&lt;/DIV&gt;
&lt;DIV&gt; char l2pad[L2_CACHE_LINE];&lt;/DIV&gt;
&lt;DIV&gt;};&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;struct slab {&lt;/DIV&gt;
&lt;DIV&gt; union header_l2pad header;&lt;/DIV&gt;
&lt;DIV&gt; unsigned char blkbuf[BLKBUF_SIZE];&lt;/DIV&gt;
&lt;DIV&gt;};&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;
&lt;DIV&gt;typedef char sassert[&lt;/DIV&gt;
&lt;DIV&gt; (sizeof(union header_l2pad)== L2_CACHE_LINE) &amp;amp;&amp;amp;&lt;/DIV&gt;
&lt;DIV&gt; (sizeof(struct slab)== PAGE_SIZE) ? 1 : -1&lt;/DIV&gt;
&lt;DIV&gt;];&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;DIV&gt;_________________________________________________________________&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;If you ensure that `struct slab' objects reside on a `PAGE_SIZE' boundary, then you can find the header from any address residing in `struct slab::blkbuf' by using the masking technique. The actual buffer space starts out aligned on a l2 cache line boundary. This is fairly trivial task indeed. If the application needs specific alignment, well, it does what they all do and over allocate and perform the alignment themselves:&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;A href="http://groups.google.com/group/comp.programming.threads/msg/f2b1cac59c8e98a3"&gt;http://groups.google.com/group/comp.programming.threads/msg/f2b1cac59c8e98a3&lt;/A&gt;&lt;/P&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;The allocator does not care if the application requests more memory than it needs because of special alignment requirements. If the application needs page alignment, well, in this setup objects larger than `BLKBUF_SIZE' would be considered large and can defer to `malloc/free', or whatever.&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 08 Oct 2008 14:36:48 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872576#M3023</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2008-10-08T14:36:48Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872577#M3024</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="margin-top: 5px; width: 100%;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/347331"&gt;Dmitriy V'jukov&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Possibly we have some misunderstanding because of terminology.&lt;/P&gt;
&lt;P&gt;What is the problem to handle objects bigger than superblock? One just have to allocate then via ::malloc. They are big so it must not be a problem. Or they can be allocated directly via mmap()/VirtualAlloc(). This is approach used in TBB's scalable malloc.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;DIV&gt;Nevermind I was thinking of something else. Sorry. One time I did a region allocator based on reserved address space, and large object could be created out of multiple contigous pages. It went something like:&lt;/DIV&gt;
&lt;DIV&gt;____________________________________________________________________&lt;/DIV&gt;
&lt;DIV&gt;#define PAGE_SIZE 8192&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;struct page {&lt;/DIV&gt;
&lt;DIV&gt; unsigned char buf[PAGE_SIZE];&lt;/DIV&gt;
&lt;DIV&gt;};&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;struct vmregion {&lt;/DIV&gt;
&lt;DIV&gt;struct page* base;&lt;/DIV&gt;
&lt;DIV&gt; size_t count;&lt;/DIV&gt;
&lt;DIV&gt; size_t max_count;&lt;/DIV&gt;
&lt;DIV&gt; size_t refs;&lt;/DIV&gt;
&lt;DIV&gt;};&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;static pthread_mutex_t g_vmregion_mtx = PTHREAD_MUTEX_INITIALIZER;&lt;/DIV&gt;
&lt;DIV&gt;static struct vmregion g_vmregion = { 0, 0,0, 0};&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;/* reserve a very large number of pages and store base in&lt;/DIV&gt;
&lt;DIV&gt; `g_vmregion::base' and max count in `g_vmregion::max_count'*/&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;struct page*&lt;/DIV&gt;
&lt;DIV&gt;vmregion_commit(&lt;/DIV&gt;
&lt;DIV&gt;size_t pages&lt;/DIV&gt;
&lt;DIV&gt;) {&lt;/DIV&gt;
&lt;DIV&gt; struct page* p = NULL;&lt;/DIV&gt;
&lt;DIV&gt; size_t count;&lt;/DIV&gt;
&lt;DIV&gt; pthread_mutex_lock(&amp;amp;g_vmregion_mtx);&lt;/DIV&gt;
&lt;DIV&gt; count = g_vmregion.count + pages;&lt;/DIV&gt;
&lt;DIV&gt; if (count &amp;lt;= g_vmregion.max_count) {&lt;/DIV&gt;
&lt;DIV&gt; p = g_vmregion.base + g_vmregion.count;&lt;/DIV&gt;
&lt;DIV&gt; g_vmregion.count = count;&lt;/DIV&gt;
&lt;DIV&gt; ++g_vmregion.refs;&lt;/DIV&gt;
&lt;DIV&gt; }&lt;/DIV&gt;
&lt;DIV&gt; pthread_mutex_unlock(&amp;amp;g_vmregion_mtx);&lt;/DIV&gt;
&lt;DIV&gt; if (p) {&lt;/DIV&gt;
&lt;DIV&gt; /* commit the pages */&lt;/DIV&gt;
&lt;DIV&gt; }&lt;/DIV&gt;
&lt;DIV&gt; return p;&lt;/DIV&gt;
&lt;DIV&gt;}&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;
&lt;DIV&gt;void&lt;/DIV&gt;
&lt;DIV&gt;vmregion_decommit(&lt;/DIV&gt;
&lt;DIV&gt;struct page* pages,&lt;/DIV&gt;
&lt;DIV&gt;size_t count&lt;/DIV&gt;
&lt;DIV&gt;) {&lt;/DIV&gt;
&lt;DIV&gt; /* decommit the pages */&lt;/DIV&gt;
&lt;DIV&gt; pthread_mutex_lock(&amp;amp;g_vmregion_mtx);&lt;/DIV&gt;
&lt;DIV&gt; --g_vmregion.refs;&lt;/DIV&gt;
&lt;DIV&gt; if (! g_vmregion.refs) {&lt;/DIV&gt;
&lt;DIV&gt; g_vmregion.count = 0;&lt;/DIV&gt;
&lt;DIV&gt; }&lt;/DIV&gt;
&lt;DIV&gt; pthread_mutex_unlock(&amp;amp;g_vmregion_mtx);&lt;/DIV&gt;
&lt;DIV&gt;}&lt;/DIV&gt;
&lt;DIV&gt;____________________________________________________________________&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;But, this has all the caveats that any region type allocation does. Oh well.&lt;BR /&gt;&lt;/DIV&gt;
&lt;/DIV&gt;</description>
      <pubDate>Wed, 08 Oct 2008 15:04:31 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872577#M3024</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2008-10-08T15:04:31Z</dc:date>
    </item>
    <item>
      <title>Re:  transforming single-threaded allocators...</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872578#M3025</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="margin-top: 5px; width: 100%;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/347331"&gt;Dmitriy V'jukov&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;DIV style="margin:0px;"&gt;&lt;/DIV&gt;
&lt;P&gt;Do you mean that they can be cached for a way too long (i.e. infinitely)?&lt;/P&gt;
&lt;P&gt;Caching for limited amount of time can not be a problem, because when thread dies there still can be blocks owned by that thread in use.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;DIV&gt;They can definitely be cached infinitely in certain scenarios indeed... Think of a thread which freesseveral blocks from several different threads, and caches them... However, from that point onward,the threadsimply never interacts with the allocator interface again, and stays alive for the duration of the program. Well, theslabs which hold those blocks will persist for the lifetime of the program. This can be a problem indeed...&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;In my algorithm I use reference counting trick to ensure that slabs are freed as soon as the last reference to them has been dropped. You can see example of this moment in the following algorihtms:&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;A href="http://webpages.charter.net/appcore/vzoom/malloc/sergey_vzmem_thread.html"&gt;http://webpages.charter.net/appcore/vzoom/malloc/sergey_vzmem_thread.html&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;A href="http://groups.google.com/group/comp.programming.threads/browse_frm/thread/eb87f9cb2cb62d84"&gt;http://groups.google.com/group/comp.programming.threads/browse_frm/thread/eb87f9cb2cb62d84&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;A href="http://webpages.charter.net/appcore/vzoom/malloc/vzmalloc_win_v000_c.html"&gt;http://webpages.charter.net/appcore/vzoom/malloc/vzmalloc_win_v000_c.html&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;All of those algorithms use the same basic reference counting trick. However, it only works because there is no remote caching. Well, there is definitely one way to solve this problem: You could require the application threads to periodically or episodically free a NULL pointer, or call a special allocator function (e.g., mflush()), which would scan the calling threads cache and perform cleanup as necessary. Humm, what do you think?&lt;BR /&gt;&lt;/DIV&gt;</description>
      <pubDate>Wed, 08 Oct 2008 15:17:01 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/transforming-single-threaded-allocators/m-p/872578#M3025</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2008-10-08T15:17:01Z</dc:date>
    </item>
  </channel>
</rss>

