- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在使用 C++ 绑定(bind)在 OpenCL 中编程。我有一个问题,在 NVidia 硬件上,我的 OpenCL 代码自发地产生非常大的数字,然后(在下一次运行时)一个“1.#QNaN”。我的代码几乎是使用方程 x = vt * .5at^2 的简单物理模拟。我唯一注意到的奇怪之处是粒子的速度突然飙升到大约 6e+34,我猜这是该机器上的最大浮点值。然而,在此之前的速度/力非常小,通常值小于 1。
我使用的特定 GPU 是 Tesla M2050,具有最新的驱动程序。我使用我的 AMD Fusion CPU 作为平台(它没有专用 GPU)在我的笔记本电脑上进行原型(prototype)设计,但那里没有出现问题。我不确定这是 NVidia 驱动程序问题、我的计算问题还是完全是其他问题。
这是内核代码(注意:我有理由相信质量总是非零的):
_kernel void update_atom(__global float4 *pos, __global float4 *vel, __global float4 *force,
__global const float *mass, __global const float *radius, const float timestep, const int wall)
{
// Get the index of the current element to be processed
int i = get_global_id(0);
float constMult;
float4 accel;
float4 part;
//Update the position, velocity and force
accel = (float4)(force[i].x/mass[i],
force[i].y/mass[i],
force[i].z/mass[i],
0.0f);
constMult = .5*timestep*timestep;
part = (float4)(constMult*accel.x,
constMult*accel.y,
constMult*accel.z, 0.0f);
pos[i] = (float4)(pos[i].x + vel[i].x*timestep + part.x,
pos[i].y + vel[i].y*timestep + part.y,
pos[i].z + vel[i].z*timestep + part.z,
0.0f);
vel[i] = (float4)(vel[i].x + accel.x*timestep,
vel[i].y + accel.y*timestep,
vel[i].z + accel.z*timestep,
0.0f);
force[i] = (float4)(force[i].x,
force[i].y,
force[i].z,
0.0f);
//Do reflections off the wall
//http://www.3dkingdoms.com/weekly/weekly.php?a=2
float4 norm;
float bouncePos = wall - radius[i];
float bounceNeg = radius[i] - wall;
norm = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
if(pos[i].x >= bouncePos)
{
//Normal is unit YZ vector
pos[i].x = bouncePos;
norm.x = 1.0f;
}
else if(pos[i].x <= bounceNeg)
{
pos[i].x = bounceNeg;
norm.x = -1.0f;
}
if(pos[i].y >= bouncePos)
{
//Normal is unit XZ vector
pos[i].y = bouncePos;
norm.y = 1.0f;
}
else if(pos[i].y <= bounceNeg)
{
//etc
pos[i].y = bounceNeg;
norm.y = -1.0f;
}
if(pos[i].z >= bouncePos)
{
pos[i].z = bouncePos;
norm.z = 1.0f;
}
else if(pos[i].z <= bounceNeg)
{
pos[i].z = bounceNeg;
norm.z = -1.0f;
}
float dot = 2 * (vel[i].x * norm.x + vel[i].y * norm.y + vel[i].z * norm.z);
vel[i].x = vel[i].x - dot * norm.x;
vel[i].y = vel[i].y - dot * norm.y;
vel[i].z = vel[i].z - dot * norm.z;
}
下面是我将信息存储到内核中的方式。 PutData 只是使用 std::vector::push_back 函数将原子的位置、速度和力转换为相应的 vector ,内核只是我为 OpenCL 库编写的包装类(你可以相信我,我把正确的将参数放入入队函数的正确位置)。
void LoadAtoms(int kernelNum, bool blocking)
{
std::vector<cl_float4> atomPos;
std::vector<cl_float4> atomVel;
std::vector<cl_float4> atomForce;
for(int i = 0; i < numParticles; i++)
atomList[i].PutData(atomPos, atomVel, atomForce);
kernel.EnqueueWriteBuffer(kernelNum, posBuf, blocking, 0, numParticles*sizeof(cl_float4), &atomPos[0]);
kernel.EnqueueWriteBuffer(kernelNum, velBuf, blocking, 0, numParticles*sizeof(cl_float4), &atomVel[0]);
kernel.EnqueueWriteBuffer(kernelNum, forceBuf, blocking, 0, numParticles*sizeof(cl_float4), &atomForce[0]);
}
void LoadAtomTypes(int kernelNum, bool blocking)
{
std::vector<cl_float> mass;
std::vector<cl_float> radius;
int type;
for(int i = 0; i < numParticles; i++)
{
type = atomList[i].GetType();
mass.push_back(atomTypes[type].mass);
radius.push_back(atomTypes[type].radius);
}
kernel.EnqueueWriteBuffer(kernelNum, massBuf, blocking, 0, numParticles*sizeof(cl_float), &mass[0]);
kernel.EnqueueWriteBuffer(kernelNum, radiusBuf, blocking, 0, numParticles*sizeof(cl_float), &radius[0]);
}
一如既往,我的代码还有更多内容,但这是与内核相关的内容。
我看到了this question ,这是相似的,但我尽可能地使用 cl_float4,所以我不认为这是一个对齐问题。没有任何其他相关问题。
我意识到这可能不是一个简单的问题,但在我们可以在办公室获得新硬件进行测试之前,我的想法已经用完了。谁能帮帮我?
最佳答案
既然没有人回答,我想我会贡献我目前学到的东西。
我没有一个明确的结论,但至少,我弄清楚了为什么它经常这样做。因为我正在运行这个(和其他类似的内核)来计算时间顺序的估计值,所以我正在清除列表,调整它们的大小,然后重新运行计算。然而,我没有做的是调整缓冲区的大小。这导致一些未定义的数字被线程提取。
但是,这并不能解决我在长时间运行程序时遇到的 QNaN。那些只是自发出现的。也许这是我忽略的类似问题,但我不能说。如果有人对此问题有进一步的意见,我们将不胜感激。
关于c++ - OpenCL 在 NVidia 硬件上生成 QNaN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10839379/
运行 Tim Bailey 的《C 编程语言和软件设计简介》第 2 章中的以下代码在 Android 上的 C4Droid 中运行良好,但在 Windows 中使用带有 GCC 编译器的 CodeBl
我需要比较两个 std::list ,但有些 double 可能是无效数字 (QNAN)。如果任何无效数字是列表条目,比较过程将不起作用,因为相同无效值的比较将始终导致“假”。解决问题最简单、最优雅的
嘿,我从以下函数中得到“不是数字”的返回值: void Spider::setAngles(double x,double y, double l1, double l2){ double theta
我正在使用 C++ 绑定(bind)在 OpenCL 中编程。我有一个问题,在 NVidia 硬件上,我的 OpenCL 代码自发地产生非常大的数字,然后(在下一次运行时)一个“1.#QNaN”。我的
我想知道如何打印 float 是 QNAN 还是 SNAN。我已经将这些位分离为 signBit exponentBit 和 FractBits。 unsigned int sign = (i & 0
我注意到 Haskell(来自 Windows 上 Haskell 平台的 ghci 7.10.2)翻转了 QNAN 上的标志 (0/0 :: Double)从我在 C++ 中看到的(测试 MSVS
我已将 Visual Studio 配置为通过 _controlfp 函数抛出浮点异常。这适用于 NAN 和 INF,但不适用于 QNAN。 IE。安静的 NaN 不会引发异常。 Visual Stu
我正在用 C 编写一个简单的程序,它打印出值、内存中分配的字节数、每种数据类型的最大值和最小值。实际上,我只是在长双部分方面遇到问题。简单地说,它不会打印出我分配给 long double 变量的值,
背景: 我正在努力从 SQL Server 2000 迁移到 SQL Server 2005。这是为使用 SQL Native Client 通过 ODBC 与 SQL Server 通信的 C++
我是一名优秀的程序员,十分优秀!