GPGPUs

luminousone rd.hunt at gmail.com
Sat Aug 17 20:55:42 PDT 2013


On Sunday, 18 August 2013 at 01:43:33 UTC, Atash wrote:
> Unified virtual address-space I can accept, fine. Ignoring that 
> it is, in fact, in a totally different address-space where 
> memory latency is *entirely different*, I'm far *far* more iffy 
> about.
>
>> We basically have to follow these rules,
>>
>> 1. The range must be none prior to execution of a gpu code 
>> block
>> 2. The range can not be changed during execution of a gpu code 
>> block
>> 3. Code blocks can only receive a single range, it can however 
>> be multidimensional
>> 4. index keys used in a code block are immutable
>> 5. Code blocks can only use a single key(the gpu executes many 
>> instances in parallel each with their own unique key)
>> 6. index's are always an unsigned integer type
>> 7. openCL,CUDA have no access to global state
>> 8. gpu code blocks can not allocate memory
>> 9. gpu code blocks can not call cpu functions
>> 10. atomics tho available on the gpu are many times slower 
>> then on the cpu
>> 11. separate running instances of the same code block on the 
>> gpu can not have any interdependency on each other.
>
> Please explain point 1 (specifically the use of the word 
> 'none'), and why you added in point 3?
>
> Additionally, point 11 doesn't make any sense to me. There is 
> research out there showing how to use cooperative warp-scans, 
> for example, to have multiple work-items cooperate over some 
> local block of memory and perform sorting in blocks. There are 
> even tutorials out there for OpenCL and CUDA that shows how to 
> do this, specifically to create better performing code. This 
> statement is in direct contradiction with what exists.

You do have limited Atomics, but you don't really have any sort 
of complex messages, or anything like that.

>> Now if we are talking about HSA, or other similar setup, then 
>> a few of those rules don't apply or become fuzzy.
>>
>> HSA, does have limited access to global state, HSA can call 
>> cpu functions that are pure, and of course because in HSA the 
>> cpu and gpu share the same virtual address space most of 
>> memory is open for access.
>>
>> HSA also manages memory, via the hMMU, and their is no need 
>> for gpu memory management functions, as that is managed by the 
>> operating system and video card drivers.
>
> Good for HSA. Now why are we latching onto this particular 
> construction that, as far as I can tell, is missing the support 
> of at least two highly relevant giants (Intel and NVidia)?

Intel doesn't have a dog in this race, so their is no way to know 
what they plan on doing if anything at all.

The reason to point out HSA, is because it is really easy add 
support for, it is not a giant task like opencl would be. A few 
changes to the front end compiler is all that is needed, LLVM's 
backend does the rest.

>> Basically, D would either need to opt out of legacy api's such 
>> as openCL, CUDA, etc, these are mostly tied to c/c++ anyway, 
>> and generally have ugly as sin syntax; or D would have go the 
>> route of a full and safe gpu subset of features.
>
> Wrappers do a lot to change the appearance of a program. Raw 
> OpenCL may look ugly, but so do BLAS and LAPACK routines. The 
> use of wrappers and expression templates does a lot to clean up 
> code (ex. look at the way Eigen 3 or any other linear algebra 
> library does expression templates in C++; something D can do 
> even better).
>
>> I don't think such a setup can be implemented as simply a 
>> library, as the GPU needs compiled source.
>
> This doesn't make sense. Your claim is contingent on opting out 
> of OpenCL or any other mechanism that provides for the 
> application to carry abstract instructions which are then 
> compiled on the fly. If you're okay with creating kernel code 
> on the fly, this can be implemented as a library, beyond any 
> reasonable doubt.

OpenCL isn't just a library, it is a language extension, that is 
ran through a preprocessor that compiles the embedded __KERNEL 
and __DEVICE functions, into usable code, and then outputs 
.c/.cpp files for the c compiler to deal with.

>> If D where to implement gpgpu features, I would actually 
>> suggest starting by simply adding a microthreading function 
>> syntax, for example...
>>
>> void example( aggregate in float a[] ; key , in float b[], out 
>> float c[]) {
>> 	c[key] = a[key] + b[key];
>> }
>>
>> By adding an aggregate keyword to the function, we can assume 
>> the range simply using the length of a[] without adding an 
>> extra set of brackets or something similar.
>>
>> This would make access to the gpu more generic, and more 
>> importantly, because llvm will support HSA, removes the needs 
>> for writing more complex support into dmd as openCL and CUDA 
>> would require, a few hints for the llvm backend would be 
>> enough to generate the dual bytecode ELF executables.
>
> 1) If you wanted to have that 'key' nonsense in there, I'm 
> thinking you'd need to add several additional parameters: 
> global size, group size, group count, and maybe group-local 
> memory access (requires allowing multiple aggregates?). I mean, 
> I get the gist of what you're saying, this isn't me pointing 
> out a problem, just trying to get a clarification on it (maybe 
> give 'key' some additional structure, or something).

Those are all platform specific, they change based on the whim 
and fancy of NVIDIA and AMD with each and every new chip 
released, The size and configuration of CUDA clusters, or compute 
clusters, or EU's, or whatever the hell x chip maker feels like 
using at the moment.

Long term this will all be managed by the underlying support 
software in the video drivers, and operating system kernel. 
Putting any effort into this is a waste of time.

> 2) ... I kind of like this idea. I disagree with how you led up 
> to it, but I like the idea.
>
> 3) How do you envision *calling* microthreaded code? Just the 
> usual syntax?

void example( aggregate in float a[] ; key , in float b[], out
    float c[]) {
	c[key] = a[key] + b[key];
}

example(a,b,c);

in the function declaration you can think of the aggregate 
basically having the reserve order of the items in a foreach 
statement.

int a[100] = [ ... ];
int b[100];
foreach( v, k ; a ) { b = a[k]; }

int a[100] = [ ... ];
int b[100];

void example2( aggregate in float A[] ; k, out float B[] ) { B[k] 
= A[k]; }

example2(a,b);

> 4) How would this handle working on subranges?
>
> ex. Let's say I'm coding up a radix sort using something like 
> this:
>
> https://sites.google.com/site/duanemerrill/PplGpuSortingPreprint.pdf?attredirects=0
>
> What's the high-level program organization with this syntax if 
> we can only use one range at a time? How many work-items get 
> fired off? What's the gpu-code launch procedure?

I am pretty sure they are simply multiplying the index value by 
the unit size they desire to work on

int a[100] = [ ... ];
int b[100];
void example3( aggregate in range r ; k, in float a[], float b[]){
    b[k]   = a[k];
    b[k+1] = a[k+1];
}

example3( 0 .. 50 , a,b);

Then likely they are simply executing multiple __KERNEL functions 
in sequence, would be my guess.


More information about the Digitalmars-d mailing list