OpenCL 和 OpenGL SL 有任何“未定义的行为”吗?

发布于 2024-12-04 19:48:57 字数 118 浏览 0 评论 0原文

有人告诉我,C 和 C++ 具有“未定义的行为”,也就是说,如果我使用“某些构造”,相同的代码在不同平台或使用不同编译器上的行为可能会有所不同。

这同样适用于 OpenCL 和/或 OpenGL SL 吗?

I was told that C and C++ have "undefined behavior", that is, the same code might behave differently on different platforms, or using different compilers, if I use "certain constructs".

Does the same apply to OpenCL and/or OpenGL SL?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

静若繁花 2024-12-11 19:48:57

是的,根据 OpenCL 规范 1.1,该规范定义了未定义的行为前面的事情是:

OpenCL API 调用的行为,使用的内置函数
在内核内部或执行明确不存在的内核
由 OpenCL 定义。不需要符合要求的实施
指定当遇到未定义的构造时会发生什么
OpenCL

为例:

  • 5.2.1节定义了几个:
    • “从内核中使用 CL_MEM_WRITE_ONLY 创建的缓冲区或图像对象中读取”
    • “写入内核中使用 CL_MEM_READ_ONLY 创建的缓冲区或图像对象”
    • “可在多个设备上运行的 OpenCL 命令
      使用相同的 host_ptr 创建的缓冲区对象或
      重叠的宿主区域”
    • “重叠之间的并发读取、写入和复制
      使用同一缓冲区对象创建的子缓冲区对象”
  • 第 5.2.2 节还定义了一些:
    • clEnqueueReadBuffer 与使用缓冲区的其他命令
    • clEnqueueReadBuffer 同时映射缓冲区

不过,还有很多方法可以从 OpenCL 调用未定义的行为。

对于 OpenGL SL(规范),有很多很容易找到示例:

  • “未定义的行为是由于使用大于或等于数组大小或小于 0 的非常量表达式对数组进行索引而导致的”(有趣的是,如果它是const 那么它是一个编译时错误)
  • 访问向量元素也是如此。
  • 同样,对于使用数组下标表示法“读取 a 中的变化变量”,
    如果在写入之前读取顶点着色器,则返回未定义的值”
  • “如果在声明任何变量或之后使用此编译指示 [#pragma STDGL invariant(all)]
    函数,那么行为不变的输出集是未定义的”
  • “在写入它们之前读取 [gl_PointSizegl_ClipVertex] 会导致未定义的行为”
  • 等。

Yes, according to the OpenCL specification 1.1 which defines undefined behaviour in the front matter as:

The behavior of an OpenCL API call, built-in function used
inside a kernel or execution of a kernel that is explicitly not
defined by OpenCL. A conforming implementation is not required to
specify what occurs when an undefined construct is encountered in
OpenCL

For example:

  • Section 5.2.1 defines several:
    • "Reading from a buffer or image object created with CL_MEM_WRITE_ONLY inside a kernel"
    • "Writing to a buffer or image object created with CL_MEM_READ_ONLY inside a kernel"
    • "OpenCL commands that operate on multiple
      buffer objects created with the same host_ptr or
      overlapping host regions"
    • "Concurrent reading from, writing to and copying between overlapping
      sub-buffer objects created with the same buffer object"
  • Section 5.2.2 also defines a few:
    • clEnqueueReadBuffer with other commands using the buffer
    • clEnqueueReadBuffer whilst the buffer is mapped

There's plenty more ways of invoking undefined behaviour from OpenCL though.

For OpenGL SL (specification) there are quite a few easy to find examples:

  • "Undefined behavior results from indexing an array with a non-constant expression that’s greater than or equal to the array’s size or less than 0" (Interestingly if it's a const then it's a compile time error)
  • Likewise for accessing vector elements with array subscript notation
  • "Reading a varying variable in a
    vertex shader returns undefined values if it is read before being written"
  • "If this pragma [#pragma STDGL invariant(all)] is used after the declaration of any variables or
    functions, then the set of outputs that behave as invariant is undefined"
  • "Reading [gl_PointSize or gl_ClipVertex] before writing them results in undefined behavior"
  • etc.
始于初秋 2024-12-11 19:48:57

我被告知 C 和 C++ 具有“未定义的行为”,也就是说,如果我使用“某些构造”,相同的代码在不同平台或使用不同编译器上的行为可能会有所不同。

这并不是未定义行为的实际含义。这是未定义行为的结果,但这不是它的目的。

规范就是定义当你做某事时会发生什么。它说明了哪些参数值是好的,哪些是坏的。如果您通过了错误的错误,它会告诉您遇到了哪些错误以及系统的状态。如果当前状态对于您尝试执行的操作无效,则规范会解释您遇到的其他类型的错误以及这对系统随后的状态意味着什么。

当您使用定义的行为时,您依赖于您自己和实现之间的契约;该合同称为 OpenGL 规范。您依靠实现来提供规范所需的有效性检查。并且您依赖于实现按照规范执行操作。如果实施没有正确实施某些内容,那么它就违反了合同。

当规范说某些事情将导致“未定义的行为”时,这意味着做这些事情就是违反了合同。你已经离开了地图的边缘。您正在执行规范未提供定义行为的操作;你违反了协议中你的部分。

换句话说,只要您不依赖未定义的行为,您的代码就可以完美移植。这就是它的意思。

一般来说,如果测试会给实现带来繁重的负担,那么规范会标记一些未定义的东西。毕竟,OpenGL 确实需要相当快的速度。因此,他们试图避免通过强迫驾驶员测试几乎不可能检查的事情来增加驾驶员的负担。

然后,还有一些根本无法测试的测试。在 OpenGL 中,通过将图像绑定为纹理并从中采样,同时将该图像附加到 FBO 并对其进行渲染,来读取和写入同一图像是非法的。没有办法保证测试这种情况。

哦,大部分都可以测试一下。当相同的纹理绑定到 FBO 和采样器时,绘制调用可能会失败。但是这样的话,您将无法渲染到同一纹理的不同 mipmap;请记住:每个 mipmap 都是一个单独的图像。因此,您可以检查基本/最大级别范围是否允许从绑定到 FBO 的 mipmap 进行采样。但这给用户带来了沉重的负担,因为他们在渲染到不同的 mipmap 时必须不断调整基本/最大级别。对于他们来说,使用textureLOD 或类似函数从正确的 mipmap 中进行采样要容易得多。并且直到运行时您才能确定它们是否从该 mipmap 级别之外进行采样。

就像许多规范一样,OpenCL 和 OpenGL SL 具有未定义的行为。一般来说,由于同样的原因,它是未定义的:测试它会使实现速度慢得令人无法接受,或者测试根本不可能。

I was told that C and C++ have "undefined behavior", that is, the same code might behave differently on different platforms, or using different compilers, if I use "certain constructs".

That's not what undefined behavior actually means. That is the result of undefined behavior, but that's not what it's for.

Specifications are all about defining what happens when you do something. It says what parameter values are good and which are bad. If you pass bad ones, it tells you what errors you get and what the state of the system will be. If the current state is invalid for an operation you attempt to perform, the specification explains what other kinds of errors you get and what that means for the state of the system afterwards.

When you use defined behavior, you are relying on a contract between yourself and the implementation; that contract is called the OpenGL specification. You rely on the implementation to provide the validity checks that the specification requires. And you rely on the implementation doing what the specification says. If the implementation doesn't implement something correctly, then it is breaking the contract.

When the specification says that a certain set of things will result in "undefined behavior", what that means is doing those things is you are breaking the contract. You are off the edge of the map. You are doing something for which the specification does not provide defined behavior; you broke your part of the deal.

To put it another way, your code will be perfectly portable as long as you don't rely on undefined behavior. That's what it means.

Generally, the spec marks something undefined if testing for it would be an onerous burden for implementations. OpenGL does need to be reasonably fast, after all. So burdening the driver by forcing it to test for things that would be nearly impossible to check for is something they try to avoid.

Then, there are tests which are flat-out impossible to test for. In OpenGL, it is illegal to read from and write to the same image, by binding an image as a texture and sampling from it, while simultaneously attaching that image to an FBO and rendering to it. There is no way to guaranteeably test for this scenario.

Oh, you can test for most of it. You could fail on draw calls when the same texture is bound to the FBO and to a sampler. But then, you wouldn't be able to render to different mipmaps of the same texture; remember: each mipmap is a separate image. So you could check to see if the base/max level range allows for the possibility to sample from the mipmap that is bound to the FBO. But that puts a hefty burden on the user, as they would have to be constantly adjusting the base/max level when rendering to different mipmaps. It's much easier for them to just sample from the correct mipmap with textureLOD or similar functions. And you can't determine until runtime whether they are sampling from outside that mipmap level.

OpenCL and OpenGL SL have undefined behavior, just like many specifications. And generally, it's undefined for the same reasons: testing for it would make the implementation unacceptably slower, or testing is flat-out impossible.

萝莉病 2024-12-11 19:48:57

是的,存在未定义的行为(您可以 grep 规范来查找一些);但要小心,因为这些并不是程序在不同系统上表现不同的唯一方法:并非所有 OpenGL 实现都是完全兼容的(事实上,很可能大多数都不是)。例如,Nvidia 的驱动程序允许在此处的核心配置文件中调用 texture2D,而这会在其他平台上导致错误(后者是预期的行为)。了解其是否有效的最佳方法是在多个平台(操作系统、GPU 和驱动程序)上进行测试。

Yes, there are undefined behaviours (you can grep the spec to find some); but be careful, because those are not the only way for a program to behave differently on different systems: not all OpenGL implementations are completely compilant (in fact, it is likely that most aren't). For instance, Nvidia's drivers allow texture2D to be called in a core profile here, while this causes an error on other platforms (and the latter is the expected behaviour). The best way to know if it will work is to test on several platforms (OSs, GPU, and drivers).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文