CUDA计算后C#侧的NaN值

CUDA计算后C#侧的NaN值,c#,c,cuda,C#,C,Cuda,我创建了一个C#程序,它使用managedCUDA计算大量“行星”或“球”之间的天体相互作用。我让CUDA在测试单浮点和整数计算时正常工作,但现在在数组中,它似乎不能正常工作。我在C#程序和内核中都有相同的结构定义: struct Ball { float2 position; float2 velocity; float mass; }; 下面是我在C#程序中初始化内核时使用的代码: //initializes the CUDA context cuda = new

我创建了一个C#程序,它使用managedCUDA计算大量“行星”或“球”之间的天体相互作用。我让CUDA在测试单浮点和整数计算时正常工作,但现在在数组中,它似乎不能正常工作。我在C#程序和内核中都有相同的结构定义:

struct Ball
{
    float2 position;
    float2 velocity;
    float mass;
};
下面是我在C#程序中初始化内核时使用的代码:

//initializes the CUDA context
cuda = new CudaContext();

//Loads the two kernels, velocity calculation and positions updating according to the velocity
UpdateBallGravity = cuda.LoadKernel("kernel.ptx", "UpdateBallGravity");
UpdateBallPosition = cuda.LoadKernel("kernel.ptx", "UpdateBallPosition");

//allocates gpu memory for a new Ball[] and copies it
d_balls = new Ball[1024];

//generates new balls on the gpu memory
Random random = new Random();
for (int i = 0; i < d_balls.Size; i++)
{
    d_balls[i] = new Ball(
        (float)random.NextDouble() * ClientSize.X,
        (float)random.NextDouble() * ClientSize.Y,
        (float)random.NextDouble() * 20000);
}
//初始化CUDA上下文
cuda=新的CudaContext();
//加载两个内核,速度计算和根据速度更新位置
UpdateBallGravity=cuda.LoadKernel(“kernel.ptx”、“UpdateBallGravity”);
UpdateBallPosition=cuda.LoadKernel(“kernel.ptx”、“UpdateBallPosition”);
//为新球[]分配gpu内存并复制它
d_balls=新球[1024];
//在gpu内存上生成新球
随机=新随机();
对于(int i=0;i
当我准备渲染时,我放置了一个断点来检查来自gpu的值,发现在更新球的速度和位置之后,我在每个球的位置和速度成员中都得到了NaN。质量没有改变,因为我没有在内核中修改它。以下是两个内核:

__global__ void UpdateBallGravity(Ball *balls, int ballCount, float gravityInfluence)
{
    int idx = getGlobalIdx_3D_3D();
    if (idx >= ballCount)
        return;
    float2 gravity = float2();
    for (int i = 0; i < ballCount; i++)
    {
        if (i == idx)
            continue;
        Ball remote = balls[i];
        float2 difference = make_float2(remote.position.x - balls[idx].position.x, remote.position.y - balls[idx].position.y);
        float f = (balls[idx].mass + remote.mass) / lengthSquared2f(difference);
        gravity.y += difference.y*f;
    }
    balls[idx].velocity.x += gravity.x*gravityInfluence;
    balls[idx].velocity.y += gravity.y*gravityInfluence;
}

__global__ void UpdateBallPosition(Ball *balls, int ballCount)
{
    int idx = getGlobalIdx_3D_3D();
    if (idx >= ballCount)
        return;
    balls[idx].position.x += balls[idx].velocity.x;
    balls[idx].position.y += balls[idx].velocity.y;
}
\uuuu全局\uuuuu无效更新球重力(球*球,整数球数,浮点重力影响)
{
int idx=getGlobalIdx_3D_3D();
如果(idx>=球数)
返回;
float2重力=float2();
对于(int i=0;i=球数)
返回;
球[idx]。位置.x+=球[idx]。速度.x;
球[idx]。位置.y+=球[idx]。速度.y;
}

您在不检查零的情况下按长度平方d2f(差)进行偏差:这是您的NAN的原因吗?球构造器是什么样子的?它有三个输入值,但要存储五个值。。。在启动任何内核之前,Ball数组是否正确?我只是在调用任何内核之前检查了数组,这些值似乎都是正确的。我还尝试在第一次调用新内核(只将质量设置为“2”)后读取。第一个运行得很好,没有数据丢失,但是第1023个有位置。y=2!这与gpu使用不同的float2结构作为C端(我说的是位)有什么关系吗?不,float2在C和C/Cuda中是一样的。。。但C#可以将Ball结构重新排序为总共24个字节(3*8个字节)。使用属性[StructLayout(LayoutKind.Sequential)]或者更好的[StructLayout(LayoutKind.Explicit)]将球结构设置为与cuda中的完全相同。alirght几分钟后我将尝试使用[StructLayout(LayoutKind.Explicit)]现在,我已经将所有内容都更改为在任何地方都使用纯双精度,而且似乎都可以使用(如果我让它工作,我会把它改回double2结构)。现在,如果我做一个内核调用,速度大约是1.*E-308…如果我用手做同样的计算,结果显然是不一样的!在我看来,double不是相同的IEEE或类似的东西…这可能吗?