Practice YoGA¶
YoGA has been designed with simplicity in mind so that working with objects on the GPU would be as easy as with standard Yorick variables. Easiest is to start with a "hello world" example ...
Hello YoGA !¶
The following lines will show you how to manipulate yoga objects.
As in any Yorick session, computations using YoGA start with the creation of a variable.
> a=yoga_obj("float",[1,100]) Object created @ 00BF9E30
executing this line will create a YoGA object with name a, and representing an array of a hundred single floats over 1 dimension. Notice the similarity between creating a YoGA object and a standard array in Yorick. Additionally, a line informing the user about the address (on the GPU) at which the corresponding memory has been allocated is printed. This helps to follow what is happening on the GPU.
Alternatively, you can also create the exact same object with the command :
> a=yoga_obj(0.0f,[1,100]) Object created @ 0403C1B0 Object deleted @ 00BF9E30
as with a standard Yorick array. You see that this line has a peculiar effect. An object is created at a specified address but the object we created with the previous line have been deleted. This is because we ask Yorick to use the same opaque object as for the previous line. So an object is first created on the GPU, but because in Yorick it is represented by an existing Yorick object, this means that the content of the existing Yorick object has to be deleted. Hence what happens. This shows a very nice feature of YoGA. Thanks to the standard API we used, Yorick can handle automatically the allocation / desallocation of memory space on the GPU. Same automatic desallocation happens when terminating Yorick. Another simple manner for desallocating memory is as usual with Yorick :
> a=[] Object deleted @ 0403C1B0
This features allows a very sane management of the GPU memory under Yorick avoiding leaks as far as possible.
We can now check the nature of this object :
> a=yoga_obj(0.0f,[1,100]) Object created @ 0403C1B0 > a Object of type: Yoga Object
as you can see this object is what is called an "opaque object" in Yorick. You can get its content by calling the on_eval method associated to opaque objects :
> a() [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
and obviously a contains 0s. The on_eval method (simply adding parenthesis after the variable name) handles the device2host memcopy mandatory to print the content of a in the terminal. However, the content of the variable stays on the GPU and what is printed is only a temporary copy in the CPU memory of the content of the GPU variable.
now that we have created an array, we may want to fill it with something. We can, for instance, fill it with some random numbers. To do so we simply use the yoga_random function as follows :
> yoga_random,a
From this point, the GPU memory holds an array of 100 randomly generated floats in the range (0,1). yoga_random is the equivalent of the Yorick native random which generates a uniform distribution of numbers between 0 and 1. Note that here we have not specified a seed so YoGA has selected the default seed value : 1234. seed can be added as an additional parameter.
Note that doing so we have filled an existing object with random numbers. Invoking the same routine but as a function and not a sub-routine with an empty object as a result will tell Yorick to first allocate space on the GPU and then fill it with random numbers, as in the following exemple :
> b=yoga_random("float",[1,100],1234) Object created @ 0405BB00
notice that we have to tell Yorick the type (float or double) of the object. This is an intrinsic feature of YoGA, with a proper variable type management for mostly every feature. The random function in Yorick will always return a double precision result.
notice also that we have this time given a peculiar seed, which happens to be the same as the default one. So a and be must contain the exact same values. This can be verified with the on_eval method as follows:
> a()-b() [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
the on_eval method can also be used to display the results:
> plg,a()
will display the content of a in the current Yorick graphics window.
Alternatively from filling an array with random values, you may want to fill it with defined values. Here is an example of how to proceed. Let's first create an array with some floating numbers in it an transfert it to the GPU:
> c=float(indgen(100)) Object deleted @ 0405C750 > yoga_host2device,b,c > b() [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29, 30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55, 56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81, 82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]
to do the inverse operation, just use
yoga_device2host
now you can play with your objects on the GPU. Try for instance :
> yoga_dot(a,b) 2667.81
which computes the dot product of the 2 vectors or :
> yoga_imin(a) 9
which computes the position of the minimum of the vector. this can be easily verified :
> wheremin(a()) [9]
Mis à jour par Julien Brule il y a plus de 12 ans · 1 révisions