问题描述
我写了一个简单的测试,它会通过并行执行两个复制命令来创建同步问题,因此我可以有一种方法来添加同步技术,以熟悉和体验。 不幸的是,似乎有一个隐式的 sync ,因为在没有任何同步机制的情况下一切正常。
测试执行以下操作:
步骤 (2) 和 (3) 是在没有同步的情况下完成的,所以我希望将数据从 B 传输到 C 会发生,而数据仍然从 A 写入 B,这样会损坏 C 中的数据。但是读 C 到 cpu 总是显示正确的结果,它总是等于写入 A 的数据。
将缓冲区大小更改为 1G 无济于事,它仍然有完美的结果(在这种情况下并不完美 :))
硬件:Quadro RTX 5000 with Max-Q Design api版本:4202651 驱动程序:1938276352
// Given:
// VkCommandPool cp;
// VkDevice device;
// VkQueue queue;
// VkBuffer bufferA; 1G stage buffer (updated by cpu,has gpu src transfer usage)
// VkBuffer bufferB; 1G buffer (has gpu src and gpu dst transfer usage)
// VkBuffer bufferC; 1G stage buffer (read by cpu,has gpu dst transfer usage)
// create command buffer
VkCommandBufferAllocateInfo cbai = {};
cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cbai.pNext = 0;
cbai.commandBufferCount = 1;
cbai.level = VkCommandBufferLevel::VK_COMMAND_BUFFER_LEVEL_PRIMARY;
cbai.commandPool = cp;
std::vector<VkCommandBuffer> cbs(1);
vkAllocateCommandBuffers(device,&cbai,cbs.data());
// set copy info
VkCommandBufferBeginInfo cbbi = {};
cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cbbi.pNext = 0;
cbbi.pInheritanceInfo = 0;
VkBuffercopy copyRegion = {};
copyRegion.srcOffset = 0;
copyRegion.dstOffset = 0;
copyRegion.size = 1024 * 1024 * 1024;
// record copy commands
vkBeginCommandBuffer(cbs[0],&cbbi);
vkCmdcopyBuffer(cbs[0],bufferA,bufferB,1,©Region);
vkCmdcopyBuffer(cbs[0],bufferC,©Region);
vkEndCommandBuffer(cbs[0]);
// execution of command buffer
VkSubmitInfo si = {};
si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
si.commandBufferCount = 1;
si.pCommandBuffers = cbs.data();
vkQueueSubmit(queue,&si,VK_NULL_HANDLE);
// wait execution finished
vkDeviceWaitIdle(device);
// free command buffers
vkFreeCommandBuffers(device,cp,cbs.data());
解决方法
未定义行为未定义。您不能编写任何保证跨实现具有任何特定行为的 UB 代码。包括特别错误的行为。
也许存在隐式同步。或者 GPU 可能一次只能在该队列上执行一个传输操作。或者是其他东西。关键是代码有 UB,但你不能以某种方式使 UB 显化。