This project is read-only.

Creation of double3 type

Apr 16, 2015 at 7:15 PM
I have added a class in my code that makes the obvious extension of vector types.cs to add the double3 struct. In implementing the operator methods I have noticed a curious anomaly. The two non-commutative operations subtract and divide are not implemented in the same way. First of all the non-commutativity of these operations can be demonstrated as follows
3 - 1 = 1 and 1 - 3 = -2
3 / 1 = 3 and 1 / 3 = 0.3333

You have implemented the divide operation correctly but the subtract implementation is not accurate as regards the order of operands for this operation between the two functions
subtract(double, double2) and subtract(double2, double) in your code this would be in the double 2 struct. Also in the divide operation there is no attempt to guard against a divide by zero error.

I was wondering if this treatment of the non-commutativity of the subtract operation is intentional or not and whether you punted on the divide by zero expecting the processor to throw the appropriate exception. Thanks by the way for an extremely useful library.

PS. would you like me to modify your vectorType.cs to add the double3 struct?
Apr 16, 2015 at 9:39 PM
Hi,

Regarding the order of operands I’m not sure if I’m missing your point, but it seems ok to me. We have three different cases:
  • vector minus vector,
  • vector minus scalar and
  • scalar minus vector,
    i.e. subtract(double2, double2), subtract(double2, double) and subtract(double, double2).
    Also if I let the (simple and by far not very exhaustive) test cases run, things seem to be as they should. Could you please give an example for what you think should be different or point me to the wrong code?
Here are the two test cases (they are not in the repository)
[TestMethod]
public void Double2SubTest()
{
    double a = 5;
    double b = 2;

    double c1 = a - b;
    double c2 = b - a;

    double2 avec = new double2(a, a);
    double2 bvec = new double2(b, b);

    double2 c1vec = avec - bvec;
    double2 c2vec = bvec - avec;
    Assert.AreEqual(c1, c1vec.x);
    Assert.AreEqual(c1, c1vec.y);
    Assert.AreEqual(c2, c2vec.x);
    Assert.AreEqual(c2, c2vec.y);

    c1vec = avec - b;
    c2vec = bvec - a;
    Assert.AreEqual(c1, c1vec.x);
    Assert.AreEqual(c1, c1vec.y);
    Assert.AreEqual(c2, c2vec.x);
    Assert.AreEqual(c2, c2vec.y);

    c1vec = a - bvec;
    c2vec = b - avec;
    Assert.AreEqual(c1, c1vec.x);
    Assert.AreEqual(c1, c1vec.y);
    Assert.AreEqual(c2, c2vec.x);
    Assert.AreEqual(c2, c2vec.y);
}

[TestMethod]
public void Double2DivTest()
{
    double a = 5;
    double b = 2;

    double c1 = a / b;
    double c2 = b / a;

    double2 avec = new double2(a, a);
    double2 bvec = new double2(b, b);

    double2 c1vec = avec / bvec;
    double2 c2vec = bvec / avec;
    Assert.AreEqual(c1, c1vec.x);
    Assert.AreEqual(c1, c1vec.y);
    Assert.AreEqual(c2, c2vec.x);
    Assert.AreEqual(c2, c2vec.y);

    c1vec = avec / b;
    c2vec = bvec / a;
    Assert.AreEqual(c1, c1vec.x);
    Assert.AreEqual(c1, c1vec.y);
    Assert.AreEqual(c2, c2vec.x);
    Assert.AreEqual(c2, c2vec.y);

    c1vec = a / bvec;
    c2vec = b / avec;
    Assert.AreEqual(c1, c1vec.x);
    Assert.AreEqual(c1, c1vec.y);
    Assert.AreEqual(c2, c2vec.x);
    Assert.AreEqual(c2, c2vec.y);
}
The Zero-check/exception: I’m a friend of keeping things as simple as possible. If divide by zero is allowed or handled by compiler/.net/platform, I shouldn’t interfere with that. If it is not allowed the division on the single elements will throw the exception... Just by doing nothing we stay consistent with the rest of the framework.
Just an example:
double a = 3;
double b = 0;
double c = a / b;
gives no exception and c = +infinity. Why should double2 differ? (for integer .net will throw an div-by-zero-exception)

Finally adding double3 to vectorTypes.cs is definitively possible, but double3 is not a “native” cuda vector type. Not sure if this really fits here, on the other hand its existence won’t hurt anyone. I’ll let you choose if you want to share it ;-)

Cheers,
Michael
Apr 16, 2015 at 9:42 PM

Thanks for your prompt reply.

1. The commutativity issue is a product of my weak eyes and half awake state this morning so please disregard.

2. I am happy with your explanation of your policy on divide by zero and it makes sense.

3. I think that the CUDA 7.0 sdk has the double3 type. I will check on that to make sure.

David Thayer

Apr 16, 2015 at 9:44 PM

Examining vector_types.h in the Cuda 7.0 sdk I find double 3 and also <type>4 structures defined so this is definitely needed.

Apr 16, 2015 at 9:47 PM

Question on unrelated matter. In yuor documentation you state that simply assigning a host array to CudaDeviceVariable will create the device allocation and copy the data to the device memory. However I find that I have to do the following to get it to compile.

SizeT sizeData = new SizeT(double3.SizeOf * h_data.Length);

CudaDeviceVariable<float3> d_data = new CudaDeviceVariable<float3>(sizeData);

d_data.CopyToDevice(h_data);

Not a problem but your documentation seems to be misleading.

David Thayer

Apr 16, 2015 at 9:48 PM
You're right, double3 and double4 (also longlong3 etc.) were added somewhen in the cuda history and I missed that. So it would be great to incorporate your changes!

Cheers,
Michael
Apr 16, 2015 at 9:52 PM
Edited Apr 16, 2015 at 9:55 PM
CudaDeviceVariable implements implicit converter operators so that the following works, too:
float3[] array_host = new float3[100];
for (int i = 0; i < 100; i++)
{
    array_host[i] = new float3(i, i+1, i+2);
}
//alloc device memory and copy data:
CudaDeviceVariable<float3> array_device = array_host;
//alloc host array and copy data: 
float3[] array_host2 = array_device; 
and the size argument for CudaDeviceVariable-Constructor is in elements, not in bytes!
Apr 16, 2015 at 9:54 PM

I have only implemented double3 but it is rather mechanical to create these types . Would you like me to send you a file from my project and you can add it in or should I go through the process of forking your project and creating a pull request?

Apr 16, 2015 at 9:57 PM
no, just send me the file...
Apr 16, 2015 at 9:57 PM

Hmmm… I looked for that in the code thinking that since I had a new vectorized type that there was somewhere that I needed to add some code to support these. However I now see that I was confusing float3 with double3. My Bad. J

Apr 16, 2015 at 9:59 PM

Here it is

Apr 16, 2015 at 10:20 PM
I commited the changes, but I think it's not necessary to update / create a new release for this. If someone urgently needs the ready compiled binarys including double3 and 4, just post an update request here ;-)

Cheers,
Michael