问题是如何制作clang关于哪些循环(或代码的其他部分)已被矢量化的打印信息.GCC有一个命令行开关命名-ftree-vectorizer-verbose=6为这样做,但我找不到类似的东西clang.是否clang支持此或我唯一的选择是在拆卸偷看?
虽然我想我明白aggregation和composition,我有困难的理解bi-directional和uni-directional关联.我已经阅读了与bi-directional关联,两个类都知道彼此和uni-directional关联只有一个类知道这种关系.然而,这个解释对我来说似乎太抽象了,我想知道这对我的代码和我正在编写的程序有什么意义.如果你能够提供一个简单的例子说明这两个如何转换为代码(我更喜欢c ++,但它可以包括伪代码),那将是非常好的.
在尝试理解不同的坐标系时,我遇到了这个网站,其中指出:RenderMan使用left-handed coordinate system正向旋转clockwise,而OpenGL使用right-handed coordinate system正向旋转counter-clockwise.
我的问题是旋转方向和坐标系手性是否仅仅是两个不同的约定,或者这是由数学本身产生的?
同样,我知道三角形的正面顶点必须counter-clokwise在OpenGL中按方向排序.这是否与协调系统的手性有关,或者它只是另一种不相关的惯例?
第三,当x, y, z在我面前抛出带有标记为轴的随机坐标系的图片时,如何判断哪一个是左手,哪一个是右手?我知道有一条规则用右手和中间,食指和拇指,但每个人似乎都使用不同的方式.我应该如何将手指与这些轴对齐?
很抱歉可能将很多不相关的东西混合在一起,但在阅读了各种互联网资源后,事情开始在我脑海中融为一体.
我想让我的代码由编译器自动向量化,但我似乎无法做到正确。特别是我从中得到的带有-ftree-vectorizer-verbose=6
选项的消息是125: not vectorized: not suitable for gather D.32476_34 = *D.32475_33;.
现在我的问题是这条消息的全部含义以及这些数字代表什么?
波纹管,我创建了一个产生相同消息的简单测试示例,所以我假设这些问题是相关的。
static void not_suitable_for_gather(unsigned char * __restrict__ pixels, int * __restrict__ indices, int indices_num)
{
for (int i = 0; i < indices_num; ++i)
{
int idx = indices[i] * 4;
float r = pixels[idx + 0];
float g = pixels[idx + 1];
float b = pixels[idx + 2];
float a = pixels[idx + 3] / 255.0f;
pixels[idx + 0] = r;
pixels[idx + 1] …Run Code Online (Sandbox Code Playgroud) 正如标题所说,当我跑我OpenCL的内核整个屏幕停止重绘(图像显示在监视器上,直到我的程序与计算做仍然是相同的这是真实的,即使在情况下,我从我的笔记本电脑上拔下它,然后重新插入-八方通显示相同的图像)并且计算机似乎也没有对鼠标移动作出反应 - 光标停留在相同的位置.
我不确定为什么会这样.它可能是我程序中的错误,还是标准行为?
在Google上搜索时,我在AMD的论坛上找到了这个帖子,有些人认为这是正常的,因为当GPU忙于计算时,GPU无法刷新屏幕.
如果这是真的,还有什么方法可以解决这个问题吗?
我的内核计算可能需要几分钟的时间,并且我的计算机实际上几乎无法使用整个时间真的很痛苦.
EDIT1:这是我目前的设置:
编辑2:所以在玩了一天我的代码之后,我从你的回复中得到了建议并将我的算法改为这样的(伪代码):
for (cl_ulong chunk = 0; chunk < num_chunks; chunk += chunk_size)
{
/* set kernel arguments that are different for each chunk */
clSetKernelArg(/* ... */);
/* schedule kernel for next execution */
clEnqueueNDRangeKernel(cmd_queue, kernel, 1, NULL, &global_work_size, NULL, 0, NULL, NULL);
/* read out the results from kernel and append them …Run Code Online (Sandbox Code Playgroud) 我正在重构我们的代码库,其中有以下代码(简化):
template <typename T>
class TVector3;
template <typename T>
class TVector4;
template <typename T>
struct TVector4
{
TVector3<T>& V3() { return (TVector3<T> &) *this; }
const TVector3<T>& V3() const { return (const TVector3<T> &) *this; }
};
template <typename T>
struct TVector3
{
template <typename U>
constexpr TVector3(const TVector4<U>& v) noexcept { }
};
typedef TVector3<float> Vec3f;
typedef TVector4<float> Vec4f;
struct RGBA
{
Vec4f rgba;
operator Vec3f() const { return rgba.V3(); }
};
Run Code Online (Sandbox Code Playgroud)
clang 警告我returning reference to local temporary …
据我了解,如果我有一个绘制调用以某种方式使用任何先前绘制调用的结果或写入相同的渲染目标(帧缓冲区),那么我需要确保稍后的绘制调用可以看到所有先前绘制调用的内存效果抽奖。
但是,当我渲染带有一堆对象的场景时,每个这样的对象都是一个绘制调用,并且所有这些绘制调用都写入同一个帧缓冲区。
每次绘制调用后我都需要发出内存屏障吗?
例如 Sascha Willem 的 pbrbasic 示例有这段代码(有点简化),我在那里没有看到任何管道障碍:
VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
VkDeviceSize offsets[1] = { 0 };
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &models.objects[models.objectIndex].vertices.buffer, offsets);
vkCmdBindIndexBuffer(drawCmdBuffers[i], models.objects[models.objectIndex].indices.buffer, 0, VK_INDEX_TYPE_UINT32);
Material mat = materials[materialIndex];
for (uint32_t y = 0; y < GRID_DIM; y++) {
for (uint32_t x = …Run Code Online (Sandbox Code Playgroud) 我正在努力澄清我对 Vulkan 执行模型的困惑,我希望我的理解得到验证并得到我仍然不清楚的问题的答案。
所以我的理解如下:
主机和设备相对于彼此完全异步地执行。我必须使用VkFence它们之间的同步,即当我想知道某个特定提交已在设备上执行完毕时,我必须等待主机VkFence发出适当的信号。
不同的命令队列彼此异步执行。Vulkan 规范对提交到这些队列的开始或完成执行的顺序不提供任何保证。所以vkQueueSubmit队列 A 完全独立vkQueueSubmit于队列 B执行,我必须使用VkSemaphore以确保例如提交到队列 B 在提交到队列 A 完成后开始执行。
但是提交到同一个命令队列的不同命令会遵守它们的提交顺序,这意味着后面提交的命令不会开始执行,除非前面提交的命令已经开始执行,但另一方面这并不意味着这些后面的命令无法完成在较早的命令之前执行。
状态设置命令(例如vkCmdBindPipeline,vkCmdBindVertexBuffers...)不是异步的,并且稍后会延迟(例如,vkCmdDraw)。实际上,它们会立即在主机上(而不是在设备上)执行并修改状态,VkCommandBuffer并且这种累积修改的状态用于记录后面的动作命令。
从同步的角度来看,VkRenderPass可以认为只是一个更简单的管道屏障接口。它可以被认为是在渲染通道实例的开始处(代替vkCmdBeginRenderPass),在渲染通道实例的末尾(代替vkCmdEndRenderPass)和每个子通道之后有一个管道屏障(代替vkCmdNextSubpass)。
在我的脑海中,命令如何在单个命令队列上执行的心理模型是一个巨大的命令流(按照它们被记录到命令缓冲区的顺序以及这些命令缓冲区提交到队列的顺序进行排序)由管道分割障碍。每个管道屏障将流分成两部分,屏障之前的命令(A 部分)和屏障之后的命令(B 部分)。只有在 A 部分中的所有命令都完成执行流水线阶段 X 之后,才允许 B 部分中的命令开始(或者更确切地说是在流水线阶段 Y 中继续执行)。
问题:
Vulkan 规范(第 2.2.1. 队列操作)指出:
命令缓冲区提交到单个队列遵守提交顺序和其他隐式排序保证,但否则可能会重叠或乱序执行。针对单个队列的其他类型的批次和队列提交(例如稀疏内存绑定)与任何其他队列提交或批次没有隐式排序约束。
假设在我的程序中,我只有一个通用队列,可以发出各种命令(图形、计算、传输、演示等),那么上面的语句是否意味着以下内容?
vkQueueSubmit #3仅在vkQueueSubmit #2已经开始执行之后才开始执行,它仅在vkQueueSubmit #1已经开始之后开始,......但是vkQueueBindSparse或者vkQueuePresentKHR可以随时开始,无论它们何时由主机发出......换句话说,我总是必须使用VkSemaphore以确保演示 ( vkQueuePresentKHR …