> On Dec 13, 2020, at 8:39 AM, Mark Adams <[email protected]> wrote:
> 
> So how do I declare 
> 
> struct myMat {
>  PetscScalar *a;
>  PetscInt        *i, *j, nrows;
> }
> 
> so that I can use, or give me an alternative idiom, 
> 
> struct myMat h_mat, *d_mat;
> ....
> cudaMemcpy(          d_mat,   &h_mat,  sizeof(myMat),  
> cudaMemcpyHostToDevice))

   This will copy the pointers (not the entries in the arrays) which means in 
both d_mat and h_mat a and i,j refer to Kokkos (or CUDA etc) memory so 

> struct myMat {
>  PetscKokkosScalar *a;
>  PetscKokkosInt        *i, *j;
   PetscInt                    nrows;
> 
> }

   the nrows is annoying because in d_mat it refers to device memory while in 
h_mat it refers to host memory so we cannot label it clearly.

   Sorry, by code reader I meant someone reading or maintaining the code. 

   To me the above struct is clearer, I know immediately that *a and *i, *j 
point to Kokkos space. While labeled as PetscScalar *a I have to figure out 
somehow by examining other code where it points (this is a waste of time I 
think). 

> 
> And what is PetscKokkosReal*? I guess this is in the default execution space 
> in Kokkos. I guess that is fine.
> 
> But I guess I don't understand what a "code reader" is. If it's a person or a 
> compiler you could do what I do is have a variable naming convention like h_ 
> and d_. 
> 
> Junchao used _d and _h in aijkokkosimpl.hpp, and these are typed for device 
> and host. He had to type them to get it into the Kokkos API, which does type 
> checking so I think it would catch having KokkosReal be a double and 
> PetscReal be a float.
> 
> 
> 
> On Sat, Dec 12, 2020 at 5:42 PM Barry Smith <[email protected] 
> <mailto:[email protected]>> wrote:
> 
> 
>> On Dec 12, 2020, at 4:23 PM, Mark Adams <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>> 
>> 
>> On Sat, Dec 12, 2020 at 10:44 AM Barry Smith <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>>    Currently we use PetscScalar and PetscScalar * to refer to variables that 
>> could be in any memory space. On the CPU, on the GPU, in Kokkos, etc.
>> 
>>    Would it make sense to use typedef to indicate at each location the true 
>> type of the memory location when possible? 
>> 
>> No. Absolutely not.
>> 
>> Because Cuda is simple C code (eg, printf is provided but few standard libs 
>> are provided and you can't call non-device functions from the device), you 
>> can put kernels in a header file and include it in the .cu file to get Cuda 
>> code. You need to #define things like the device declaration syntax (eg 
>> __device__) and things like atomicAdd. This is how MatSetValuesDevice works.
>> 
>> The way I do deep copies in Cuda I declare a host a device struct, like:
>> 
>> Mat h_mat, *d_mat.
>> 
>> Then do cuda mallocs into pointers in h_mat, then a cuda malloc on to get 
>> d_mat. Then a cuda copy-to-device to put any data (cuda malloced) or 
>> metadata (eg, array size, dim, etc) from h_mat into d_mat. I don't know how 
>> I could do this if h_mat and d_mat are not the same without even more 
>> gymnastics.
> 
> Oh, you would not need to change your code at all, the only difference is in 
> certain places you would have variables declared as PetscKokkosReal that 
> point to Kokkos memory instead of declared as PetscReal.  It is, as Jed 
> notes, just for readers/maintainers of the code ease.
> 
>> 
>> The Kokkos people have been working with this for a long time and I think 
>> they have probably learned the hard way what works. I would look at what 
>> they do. If they or SYCL does it I would take a look.
> 
>    CUDA has always had the same syntax for pointers to GPU memory and CPU 
> memory; this seemed odd to me because it means each code reader has to find 
> out some other way which pointers actually refer to host memory and which 
> point to GPU memory instead of just directly saying it.  Kokkos seems to have 
> just inherited this approach.  Of course with unified memory there is no 
> distinguishing so maybe no reason to have different names.
>> 
>>  
>> 
>>    typedef PetscReal PetscKokkosReal   means the variable is in the Kokkos 
>> memory space
>> 
>> There is no such thing. THere is the default execution space, default host 
>> space, Cuda memory space, etc.
>>  
>>    typedef PetscReal PetscCUDAReal
>>    typedef PetscReal PetscNVSHEMReal
>> 
>>    etc. 
>> 
>>   Then one could write things like 
>> 
>>   struct {
>>      ...
>>      PetscNVSHEMReal *values;
>>   }
>> 
>>   Similarly inside kernels one would use the type type associated with the 
>> kernel, cuda with cuda etc. 
>> 
>>   I think the resulting code will be much clearer and easier to dive into, 
>> then having to first figure out where each variable lives.
>> 
>>   I find the current code confusing because one cannot immediately see a 
>> variable declaration and know where it lives, even though it does live 
>> somewhere in particular..
>> 
>>   Barry
>> 
>> 
>> 
>> 
>> 
> 

Reply via email to