<div dir="ltr"><div>On Mon, Sep 19, 2016 at 3:51 AM, Anastasia Stulova <span dir="ltr"><<a href="mailto:Anastasia.Stulova@arm.com" target="_blank">Anastasia.Stulova@arm.com</a>></span> wrote:<br></div><div><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">



<div>
Hi Bekket,<br>
<br>
Could you please elaborate what benefits passing captured variables as separate argument gives in comparison to passing a pointer to a chunk of captures located somewhere in contiguous memory. Perhaps examples could be helpful or if you already have a patch
 feel free to setup the review.</div></blockquote><div><br></div><div>Sure, we would set up a code review later.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
<br>
Current design passes the whole block literal structure into __enqueue_kernel_XXX and relies on it to make capturing data available before enqueueing the block. Using memcpy should be sufficient here to copy thread local (private address space) data into some
 global memory.</div></blockquote><div><br></div><div><div>Of course one can copy captured variables to some global memory, but global memory management is non trivial. Which either we need some special help from target specific APIs for better management, or we need to allocate a large chunk, static size, of global memory in our OCL runtime implementation. We think both of them are not neat and less flexible(due to the static size of global memory) in comparison to passing function arguments(to block invoke function) "locally". </div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>I am guessing the same should be done with your approach but in the format of parameter passing if blocks are to be enqueued anywhere globally on the device?</div></blockquote><div><br></div><div><div>Yes, one key feature of current(ObjC) block literal structure is that it arrange captures variables in a pretty "strange" way:</div><div><br></div><div>struct block_literal {</div><div> int isa;</div><div> (...other block header fields...)</div><div> </div><div> int capture_1;   //<-- How do we know the offset of this field within our OCL runtime implementation?</div><div> float capture_2;</div><div>}</div><div><br></div><div>As mentioned in the code comment above, although we can get the offset of each fields in block_literal during codegen, it's nearly impossible to do so in a OCL runtime implementation code, i.e "outside" the compiler. In another word: The layout of block_literal is dynamic, which bothers developers.</div><div>cap_copy_helper, which is the helper "memcpy" generated(function definition included) during codegen, comes to this aid.</div></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
In your proposal does frontend generate definitions of cap_copy_helper functions then? </div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
<br>
Cheers,<br>
Anastasia
</div></blockquote><div><br></div><div>Cheers,</div><div>McClane</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><hr style="display:inline-block;width:98%">
<div dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Bekket McClane <<a href="mailto:bekket.mcclane@gmail.com" target="_blank">bekket.mcclane@gmail.com</a>><br>
<b>Sent:</b> 17 September 2016 05:12:03<br>
<b>To:</b> <a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<b>Cc:</b> Anastasia Stulova; <a href="mailto:aleksey.bader@mail.ru" target="_blank">aleksey.bader@mail.ru</a>; <a href="mailto:yaxun.liu@amd.com" target="_blank">yaxun.liu@amd.com</a><br>
<b>Subject:</b> [RFC] Block captured variables in OpenCL 2.X dynamic parallelism</font>
<div> </div>
</div><div><div class="gmail-h5">
<div>
<div dir="ltr">Hi,
<div>OpenCL 2.X dynamic parallelism in clang 3.9 leverages most of the Objective-C's block structure to save captured variables from parent kernel. However, there is a disadvantage on this design: The block literal structure, which needs to be passed to child
 kernel by address later, is allocated in parent kernel context by default. But parent kernels and child kernels only shares the global address space, so we either need to put block literal structures in global address space, which brings other problems like
 memory management due to the large amount of block literals potentially, or find another way to figure this out. </div>
<div><br>
</div>
<div>We propose a way that passes all the captured variables as function arguments to the child kernel invoke function, which is the "main body" function of child kernel. OpenCL 2.X spec doesn't allowed __local variables to be captured into child kernel block,
 so we can almost assert that there are only two kinds of captured variables: constants(i.e by-value variables) and __global pointers. Also, OpenCL 2.X allows child kernels shared chunks of memory which are passed as arguments in(and only in) __local pointer
 type to child kernel block. Thus, if we insert all the captured variables to the head of the child block invoke function argument list, which originally contains only __local pointers if there are shared memory chunks, we can not only conveniently distinguish
 captured variables from shared memory pointers based on their types in the argument list, but also remove the need of maintaining memory for block literal structures since we don't pass it to child kernel anymore. </div>
<div><br>
</div>
<div>Nevertheless, captured variables still needed to be extracted inside most of the __enqueue_kernel_XXX <wbr>implementations. We came up with a design that adds two new fields into the block literal struct: cap_num, which tells the amount of captured variables,
 and cap_copy_helper, which is a function with prototype:</div>
<div>    size_t cap_copy_helper(void* block_literal, unsigned int arg_index, void* dest_memory)</div>
<div>The second parameter arg_index requires index of the desired captured variables in block invoke function argument list mentioned above. This helper would copy your desired variable value from block_literal to dest_memory and return its size. Actually we
 had previously built a version of helper function that still took block_literal and arg_index but return the captured variables's pointer(in void* type) directly. In that approach neither can we know the size of variable nor could we retrieve value from the
 returning pointer due to the lack of type information and one can not directly de-reference a void pointer either. The new cap_copy_helper approach can solve both of the problems, although it seems to be more suitable for copying all the captured variables
 adjacently into a chunk of memory, I think it still can be used to fetch individual captured variable.</div>
<div><br>
</div>
<div>We have implemented a prototype for all of the design above except the cap_copy_helper, but it could be finished soon. Also, discussions for captured variables in advanced type like image_t are welcomed - since we haven't covered those types yet.</div>
<div><br>
</div>
<div>Yours sincerely,</div>
<div><br>
</div>
<div>-- <br>
<div>
<div dir="ltr">Bekket McClane
<div>Department of Computer Science,</div>
<div>National Tsing Hua University</div>
</div>
</div>
</div>
</div>
</div>
</div></div></div>

</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr">Bekket McClane<div>Department of Computer Science,</div><div>National Tsing Hua University</div></div></div>
</div></div></div>