小编ktb*_*ktb的帖子

GCC 对可能有效的代码抛出 init-list-lifetime 警告?

我在带有 GCC 9.3.0 的 Debian 不稳定版上运行。

最近我参与的一个项目发生了变化,引入了类似于下面的代码。

#include <initializer_list>
#include <map>
#include <vector>

std::map<int, std::vector<int>> ex = []{
    /* for reused lists */
    std::initializer_list<int> module_options;

    return (decltype(ex)) {
        {1, module_options = {
            1, 2, 3
        }},
        {2, module_options},
    };
}();
Run Code Online (Sandbox Code Playgroud)

这个想法是初始化列表的相同子部分首先在顶部声明,std:initializer_list在第一次使用时定义并分配给变量,然后在多个地方使用。这很方便,有些人可能会争辩说更具可读性,这就是它被接受的原因。

一切都很好,直到几天前 GCC 开始init-list-lifetime对代码发出警告。我们-Werror在回归中使用,所以这对我来说回归失败了。我还尝试使用 clang 9.0.1 进行编译,但不会引发警告。

<source>: In lambda function:
<source>:12:9: warning: assignment from temporary 'initializer_list' does not extend the lifetime of the underlying array [-Winit-list-lifetime]
   12 |         }},
      |         ^
Run Code Online (Sandbox Code Playgroud)

根据cppreference …

c++ gcc language-lawyer c++11

6
推荐指数
1
解决办法
372
查看次数

GCC 的计算 goto 的 ISO C 替换

背景:

在解释器循环(或其他有限状态机)中,有几种方法可以分派操作(或基于下一个输入的跳转状态)。C 中显而易见的方法是在循环中使用 switch 语句。但是,在循环内使用 switch 存在性能问题。在最坏的情况下,开关可以被编码为一个分支序列,如果操作编码不连续(或者编译器无法推断它是连续的),就会发生这种情况。即使在编译器生成跳转表的乐观情况下,仍然有多余的跳转回调度程序(我还没有看到编译器在看到循环中的开关时内联调度)。此外,调度程序中通常有一个冗余的边界检查。

GCC 团队通过引入 Computed Goto 解决了这个问题。这是一种语言扩展,允许引用标签,稍后可以跳转到goto标签指针上使用。这生成了理想的汇编代码:一个操作码索引的跳转表,在每次操作后都带有内联调度。

题:

有没有办法使用 ISO C 生成类似的汇编代码?

笔记:

我能做到的最接近的方法是将每个操作编写为一个函数,将函数指针放在一个表中,并利用尾调用优化来生成跳转而不是调用。这个问题很明显:它依赖于可能存在也可能不存在的优化。如果没有优化,生成的代码将消耗堆栈并最终使应用程序崩溃。

我试图生成的理想汇编代码(GAS .intel_syntax,类似于 NASM 语法)

.intel_syntax  noprefix

.section .rodata
optable:
  .quad nop
  .quad add
  # more ops here

.section .text
## interpreter loop entry here
nop:
    call  nextinput          # return value = table index in rax
    jmp   [optable + rax]

add:
    # add stuff here
    call  nextinput
    jmp   [optable + rax]
Run Code Online (Sandbox Code Playgroud)

c assembly gcc micro-optimization

5
推荐指数
0
解决办法
1232
查看次数

向GPU发送大图像时间

我正在使用在Tora中使用Torch进行图像处理的CNN模型(AlexNet)。我正在修改Torch入门代码

我的问题是,我要用18个通道而不是3个通道来制作图像以训练模型,并且将这些图像发送到GPU时,要比使用3个通道发送图像的时间多20倍(每批次2.13 s)(每批0.14s)。我还试图查看将具有4个通道的图像发送到GPU所需的时间。我看到,一旦频道数量增加到3个以上,时间就会增加20倍左右。例如,即使对于具有4个通道的图像,每批也要花费2秒钟的时间,这比运行3个通道的图像大约多19倍。

我想知道是否有一个导致花费这么多时间的错误,是否没有任何错误,是否有办法减少运行时间?

optimization lua gpu image-processing torch

5
推荐指数
1
解决办法
108
查看次数

拆分 pybind11 模块和自动类型转换问题

我有一组用 C++ 编写并使用 pybind11 导出到 Python 的模块。所有这些模块都应该能够独立使用,但它们使用在实用程序库中定义的一组通用自定义类型。

在每个模块中都有类似于下面的代码。的Color.hpp报头定义了在实用程序库所使用的类型。

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <string>
#include "Color.hpp"

std::vector<Color> buncha_colors(int n, std::string &color) {
    std::vector<Color> out;
    for (;n-- > 0;) {
        out.push_back(Color(color));
    }
    return out;
}

PYBIND11_MODULE(pb11_example_module, m) {
    m.def("buncha_colors", &buncha_colors);
}
Run Code Online (Sandbox Code Playgroud)

当然,这行不通。Pybind 不知道如何对Color对象进行类型转换。答案(或希望不是)是将Color类定义为模块的一部分。之后,pybind 能够进行自动类型转换。

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <string>
#include "Colors.hpp"

std::vector<Color> buncha_colors(int n, std::string &color) {
    std::vector<Color> out;
    for (;n-- > 0;) {
        out.push_back(Color(color));
    }
    return out;
}

PYBIND11_MODULE(pb11_example_module, m) {
    pybind11::class_<Color>(m, "Color") …
Run Code Online (Sandbox Code Playgroud)

c++ python pybind11

5
推荐指数
1
解决办法
915
查看次数

调用具有可转换类型的重载函数时的模板化构造函数模糊性

我有2个具有单参数模板化构造函数的类。一个是整数类型的全部,另一个是用于绑定任何可迭代对象的。对于每种类型的特定函数,我都有两个重载。如果我使用整数类型或字符串或对至少一个类有用的函数来调用函数,则会收到有关调用歧义的错误。

#include <string>

class A {
public:
    template <typename Iterable>
    A(Iterable it) : s(it.begin(), it.end()) {} 
private:
    std::string s;
};

class B {
public:
    template <typename Integer>
    B(Integer i) : i(i + 1) {}
private:
    int i;
};

void Use(A a)
{
   // some thing
}

void Use(B b)
{
    // some other thing
}

int main(void)
{
    Use(0);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器似乎对多态集的关注程度还不足以确定确实只有一种可能的解决方案。难道是因为在函数重载之前“解析了”模板吗?如何给编译器一些帮助?

c++ templates constructor overloading overload-resolution

4
推荐指数
1
解决办法
60
查看次数

libc包含不遵守源类型参数更改的防护

如果我包含time.h,请更改“源类型参数”并重新包含该标头,它是否不应该在这些新定义中添加?我了解这是由于包括警卫而发生的。我的问题是:这是libc中的错误吗?它不应该能够处理吗?

#include <time.h>
#define _XOPEN_SOURCE 600
#include <time.h>

static struct timespec t;
Run Code Online (Sandbox Code Playgroud)

错误信息:

example.c:5:24: error: storage size of ‘t’ isn’t known
    5 | static struct timespec t;
      |                        ^
Run Code Online (Sandbox Code Playgroud)

背景

我发现这种行为在使用编译时构建了Python扩展-std=c99。如果在包含标准库之前包含标准库,Python.h由于缺少POSIX功能的定义,将会出现编译错误。如果我将Python.hinclude 放在所有其他内容之前,那么一切都很好。当然也可以进行编译-std=gnu99。但是我想深入了解为什么发生错误,并将其提炼为上述代码示例。

这就引出了另一个问题。如果上述行为不是错误,那么_XOPEN_SOURCE在标头中设置和类似的源类型参数是否被视为不良做法?Python是否应该在其标头中删除该参数的设置,而是要求用户在编译期间进行定义或使用std=gnu99

c libc

4
推荐指数
1
解决办法
51
查看次数