了解C++constexpr性能

我最近使用constexprC++17 的函数编写了一个编译时光线追踪器。完整的源代码可以在这里看到。此问题的相关代码如下所示:

constexpr auto image = []() {
        StaticImage<image_width, image_height> image;

        Camera camera{Pointf{0.0f, 0.0f, 500.0f},
                      Vectorf{0.0f},
                      Vectorf{0.0f, 1.0f, 0.0f},
                      500.0f};

        std::array<Shapes, 1> shapes_list{Sphere{Pointf{0.0f}, 150.0f}};
        std::array<Materials, 1> materials_list{DefaultMaterial{}};
        ShapeContainer<decltype(shapes_list)> shapes{std::move(shapes_list)};
        MaterialContainer<decltype(materials_list)> materials{
            std::move(materials_list)};

        SphereScene scene;
        scene.set_camera(camera);

        Renderer::render(scene, image, shapes, materials);
        return image;
    }();

其中每个这里示出的类(StaticImageCameraShapesMaterialsShapeContainerMaterialContainer,和SphereScene)由完全constexpr的功能。Renderer::renderconstexpr负责循环图像中的每个像素,将光线射入场景,并设置相应的颜色。

使用当前的设置和 512x512 的图像,在发布模式下使用 MSVC 16.9.2,编译器需要大约 35 分钟来完成生成图像。在此过程中,其内存使用量上升到最终使用近 64GB RAM 的程度。

所以,我的问题是:为什么编译时间和内存使用率这么高?

我的理论是编译时间的部分原因是调用堆栈的复杂性(即大量模板、CRTP 和深度),所以我尝试通过删除几个模板来稍微简化调用堆栈(Vector类不是例如更长的模板)并设法将编译时间减少到 32 分钟,并将内存使用量减少到 61GB。更好,但仍然很高。问题是我不太明白为什么它这么慢。我确实理解评估所有constexpr函数是一个非常复杂的过程(因为编译器必须检查 UB、类型推导等),但我没想到它会这么慢。我也对高内存使用率感到困惑。图像数组本身使用不超过 4MB 的内存 ( 512 * 512 * 3 * sizeof(float)) 那么额外的内存来自哪里?

以上是了解C++constexpr性能的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>