rouge

rouge

@rouge

  • :face_with_open_eyes_and_hand_over_mouth::face_with_open_eyes_and_hand_over_mouth::face_with_open_eyes_and_hand_over_mouth:

    Post #2
  • Lskyi:

    不过我在程序运行中还从来没有进入死循环

    但是 考虑到可能是 input_vertices() 速度过快,导致从来没有进入到循环的第一个判断代码块,于是我在 RasterizerRenderer::render()(也就是渲染主线程)中,在拉起 worker 到开始 input 顶点之间,加入了 std::this_thread::sleep_for(std::chrono::seconds(2)); 这确保了 vertex_woker 存在至少一次判空的情况。

    也许是设备性能的原因,总是进入到`eb fe`中,我或许应该换一台性能更好的设备进行测试。
    Lskyi:

    这个数据竞争问题可以说是相当惊人,这么看不上锁情况下对一个队列判空在 O3 下是一个不可接受的操作。

    你说的对,似乎每个 worker_thread 中的队列判空在 O3 下都存在问题,如 `Rasterizer::worker_thread()` ![image|690x447](/uploads/image/9a/3a/9a3aa7f4e8f74cccf1ba5fd8a97167605828592d66b80c26305361a933b38eaf.avif)

    btw,我注意到,dandelion 存在一个分支 以解决这个问题,但是还需要更多测试:
    image|690x384
    不过,新分支的我目前发现了两个问题,1 是编译出现了conflicting declaration,原因似乎是在 graphics_interface.h 中,vertex_finishrasterizer_finishfragment_finish 被声明为 volatile static bool,而在 rasterizer_renderer.cpp 中,它们重新定义为 bool
    2 是当我手动将 rasterizer_renderer.cpp 中的定义和头文件中的统一后,编译后依然存在eb fe问题,其他的问题还未测试

    image|690x460


    另外麻烦问一下助教老师,在当前情况下本题如何验收。 🫠

    Post #4 ❤️ 1 like
  • 问题描述

    感谢提问,我也有类似的问题。
    首先对于:

    原项目其他线程与队列相关的我都没修改

    我也同样没有修改。

    我的问题是:我也出现了 Debug 模式编译运行能够正常渲染出结果,而 Release 模式下则不能。但是面临的具体问题略有出入 🤔: 我的程序会持续运行,卡死在渲染前(或者说有什么东西阻止了程序运行渲染的代码):
    image|690x254


    分析&临时解决思路

    通过定位发现问题出现在 VertexProcessor::worker_thread()。我猜测是 Release 模式下 O3 优化的原因,即编译器优化了第一个if (vertex_queue.empty()) {continue;}循环。于是我在 continue 上一行添加 printf("\n");(或者任何一个简单的 syscall) 以防止编译器优化这条 continue,编译运行,可以在 Release 模式下正常渲染。( 这或许可以作为一种临时的解决思路 🧐)

    void VertexProcessor::worker_thread()
    {
        while (true) {
            VertexShaderPayload payload;
            {
                if (vertex_queue.empty()) {
                    printf("\n");  // 插入这一行代码以防止编译器优化这个 continue
                    continue;
                }
    // 省略下面的代码
    

    验证优化错误

    于是,我 Release 模式下,分别对下面两种情形构建 dandelion

    1. 在上文所描述的地方添加 printf 以避免编译器优化 continue
    2. 不添加 printf,及保留 VertexProcessor::worker_thread() 原貌

    然后对构建的 dandelion 进行反汇编,如下图所示 (这里我手动使用 --- 省略非跳转相关指令,以将代码呈现在一页内)。其中左侧为添加 printf 的反汇编结果,右侧为不含 printf 的反汇编结果。
    undefined|690x449

    • 左侧代码从第一个跳转开始:

      • cmp... + je d0770 -> call printf->jmp d065a->cmp... + je d0770
      • 这对应着if (vertex_queue.empty()) {continue;}。同实际运行结果一样,一切正常
    • 右侧代码从第一个跳转开始(有两个选择):

      • empty 返回 false,直接往后执行:d0656: jmp d0755->d0755: cmp...+jne d0660->d0660: call mutex_lock
      • empty 返回 true,不往后执行:d0656: jmp d0755->d0755: cmp...+jne d0660 + jmp d0763->d0763: jmp d0763
      • 发现当程序进入 d0763 时,并非回到对 empty 的判断,而是进入了一个死循环:无条件 jmp 自身 (jmp IP - 2),我猜测这应该是 Release 模式下编译执行时陷入无限运行的原因。

    于是,我直接修改 dandelion 中这一部分的代码,直接使用 c3c3 也就是ret ret替代原有的eb fe也就是jmp IP - 2。保存后运行,函数直接返回并退出程序,说明此处确实存在死循环的代码。因此可以怀疑开头所描述的程序卡死在渲染前的原因就来自于此。
    image|690x301


    关于编译优化和多线程方面的概念我了解较少 🥺,上面的判断可能存在错误。希望能够得到解答与指导

    环境如下:
    image|665x499

    Post #2 ❤️ 2 likes
  • 感谢回复😊

    Post #5
  • 三、简答题:

    1. 简述马克思主义物质观和现实意义
    2. 量变质变规律的内容
    3. 为何实践是检验真理的唯一标准
    4. 认识为什么是不断循环往复的

    四、材料题:

    1. 两个材料,第一个是总书记的话,第二段来自《求是》,问题如下:
      1)结合材料分析文化对于社会发展的意义
      2)分析为什么要加强文化建设(也许是?)
    2. 第一问是阐述资本主义的基本矛盾和经济危机的产生;第二位问是结合材料分析为什么”资本主义必将灭亡,社会主义必将胜利“
    Post #4 ❤️ 4 likes
  • 数字评价(0 ~ 5)

    • 难度:1
    • 作业量:1
    • 收获感:5
    • 幸福指数:4

    文字评价

    课程本身不是很难,但是学校的课本编的不是很好,如果感兴趣或者希望深入学习的话仅靠课本可能会有些困难。而且老师不是数学系的,上课基本上是在念 ppt 和她的手稿讲义,对于很多问题回答的可能不是很理想。

    当然要说优点也是有的,就是不查考勤,一百多人的课很多时候只会到 50 人左右,但是考勤总是满的。。。而且几次小测对于作弊等行为是睁一只眼闭一只眼的。

    总之就是,如果对数学感兴趣且希望上课能学到一些的话可以考虑避开,此外还是可以选的。

    Post #3 ❤️ 1 like