pure是一个函数属性,表示函数不会修改任何全局内存.
const是一个函数属性,表示函数不读取/修改任何全局内存.
鉴于该信息,编译器可以进行一些额外的优化.
GCC示例:
float sigmoid(float x) __attribute__ ((const));
float calculate(float x, unsigned int C) {
float sum = 0;
for(unsigned int i = 0; i < C; ++i)
sum += sigmoid(x);
return sum;
}
float sigmoid(float x) { return 1.0f / (1.0f - exp(-x)); }
Run Code Online (Sandbox Code Playgroud)
在该示例中,编译器可以将函数计算优化为:
float calculate(float x, unsigned int C) {
float sum = 0;
float temp = C ? sigmoid(x) : 0.0f;
for(unsigned int i = 0; i < C; ++i)
sum …
Run Code Online (Sandbox Code Playgroud) 我有一个C++类,它是日志系统的前端.它的日志记录功能是使用C++ 11的可变参数模板实现的:
template <typename... Args>
void Frontend::log(const char *fmt, Args&&... args) {
backend->true_log(fmt, std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
每个日志记录后端都实现自己的版本true_log
,除其他外,它使用转发的参数进行调用vsnprintf
.例如:
void Backend::true_log(const char *fmt, ...) {
// other stuff..
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, buffer_length, fmt, ap);
va_end(ap);
// other stuff..
}
Run Code Online (Sandbox Code Playgroud)
一切都很好,我很高兴.
现在,我想对log()
参数添加静态检查:具体来说,我想使用GCC的printf格式属性.
我开始使用标记log()
函数__attribute__ ((format (printf, 2, 3)))
(因为this
第一个"隐藏"参数,我需要将参数索引移动一个).这不起作用,因为如果失败并出现编译错误:
error: args to be formatted is not ‘...’
Run Code Online (Sandbox Code Playgroud)
然后,我尝试将相同的属性添加到该true_log()
函数中.它编译,但实际上没有执行错误检查:我试图传递log()
一些无效的格式/变量组合,并且没有发出警告.也许这种检查"太晚了",换句话说,有关变量的信息已经在调用链中丢失了?
作为最后的手段,如果我注释log()
有__attribute__ ((format (printf, 2, 0)))
,我会收到关于错误的格式字符串警告,但无诊断会为无效的格式/变量组合发出.
总结问题: …
我有一些手工向量化的 C++ 代码,我正在尝试通过函数多版本化制作可分发的二进制文件。由于代码对不同指令集(SSE2、AVX2、AVX512)使用 SIMD 内在函数,因此它使用模板专业化来决定使用哪些内在函数。
整体结构大致如下:
template <unsigned W, unsigned N> struct SIMD {}; // SIMD abstraction
template <> struct SIMD<128, 8> { // specialization for specific dimensions
using Vec = __m128i;
static always_inline Vec add(Vec a, Vec b) { return _mm_add_epi8(a, b); }
... // many other SIMD methods
};
... // many other dimension specializations for different instruction sets
template <unsigned W, unsigned N> class Worker {
void doComputation(int x) {
using S = SIMD<W, N>;
... // …
Run Code Online (Sandbox Code Playgroud) 假设我需要将传入数据写入云上的数据集。我何时、何地以及是否需要在代码中使用数据集,取决于传入的数据。我只想获取对数据集的引用一次。实现这一目标的最佳方法是什么?
启动时初始化为全局变量并通过全局变量访问
if __name__="__main__":
dataset = #get dataset from internet
Run Code Online (Sandbox Code Playgroud)这看起来是最简单的方法,但即使从不需要它也会初始化该变量。
第一次需要数据集时获取引用,保存在全局变量中,并通过get_dataset()
方法访问
dataset = None
def get_dataset():
global dataset
if dataset is none
dataset = #get dataset from internet
return dataset
Run Code Online (Sandbox Code Playgroud)第一次需要数据集时获取参考,保存为函数属性,并通过get_dataset()
方法访问
def get_dataset():
if not hasattr(get_dataset, 'dataset'):
get_dataset.dataset = #get dataset from internet
return get_dataset.dataset
Run Code Online (Sandbox Code Playgroud)任何其他方式
Objective C中的不可用属性有什么作用?
__attribute__((unavailable("message")))
Run Code Online (Sandbox Code Playgroud)
Clang中有这个和其他属性的在线参考吗?
我希望只有登录用户具有所需的权限级别才能执行不同的功能.
为了让我的生活更复杂,我只想使用装饰器.下面我尝试permission
在'装饰'功能上设置属性- 如下所示.
def permission(permission_required):
def wrapper(func):
def inner(*args, **kwargs):
setattr(func, 'permission_required', permission_required)
return func(*args, **kwargs)
return inner
return wrapper
@permission('user')
def do_x(arg1, arg2):
...
@permission('admin')
def do_y(arg1, arg2):
...
Run Code Online (Sandbox Code Playgroud)
但当我这样做时:
fn = do_x
if logged_in_user.access_level == fn.permission_required:
...
Run Code Online (Sandbox Code Playgroud)
我收到一个错误 'function' object has no attribute 'permission_required'
我错过了什么?
python attributes decorator function-attributes python-decorators
我只是查找gcc的funciton属性(http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html)并遇到了该returns_twice
属性.
而且我绝对无能为力,在什么情况下函数可以返回两次...我快速查阅了所提到的内容vfork()
,setjmp()
但仍然不知道一个适用的场景是什么样的 - 你们中的任何人使用它还是可以解释一下?
我有一个简单的小装饰器,它将函数调用的结果缓存dict
为函数属性.
from decorator import decorator
def _dynamic_programming(f, *args, **kwargs):
try:
f.cache[args]
except KeyError:
f.cache[args] = f(*args, **kwargs)
return f.cache[args]
def dynamic_programming(f):
f.cache = {}
return decorator(_dynamic_programming, f)
Run Code Online (Sandbox Code Playgroud)
我现在想添加清空缓存的可能性.所以我改变了dynamic_programming()
这样的功能:
def dynamic_programming(f):
f.cache = {}
def clear():
f.cache = {}
f.clear = clear
return decorator(_dynamic_programming, f)
Run Code Online (Sandbox Code Playgroud)
现在让我们假设我使用这个小东西来实现Fibonacci数函数:
@dynamic_programming
def fib(n):
if n <= 1:
return 1
else:
return fib(n-1) + fib(n-2)
>>> fib(4)
5
>>> fib.cache
{(0,): 1, (1,): 1, (2,): 2, (3,): 3, (4,): 5}
Run Code Online (Sandbox Code Playgroud)
但是现在当我清除缓存时会发生一些奇怪的事情:
>>> …
Run Code Online (Sandbox Code Playgroud) 我在gcc中遇到了一个非常奇怪的行为,关于运算符和标记的函数__attribute((const))
.逻辑和算术运算符导致不同的优化,我不明白为什么.
这不是一个真正的错误,因为__attribute((const))
它只是一个暗示并且不能保证其效果,但这仍然是非常令人惊讶的.有人有任何解释吗?
这是代码.所以我定义了一个__attribute((const))
函数:
int f(int & counter) __attribute((const));
int f(int & counter) {
++counter;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后我定义了一个运算符测试宏.这是通过宏而不是模板/仿函数来完成的,以便向编译器提供简单的代码并简化优化:
int global = 0; // forces results to be computed
#define TestOp(OP) \
{ \
int n = 0; \
global += (f(n) OP f(n)); \
std::cout << "op" #OP " calls f " << n << " times" << std::endl; \
}
Run Code Online (Sandbox Code Playgroud)
最后,我按如下方式测试不同的运算符.注释与输出g++-4.8 -std=c++11 -O2 -Wall -pedantic
相同,输出为-O3
和-Ofast
int main() { …
Run Code Online (Sandbox Code Playgroud) 在大多数语言中,C 包括堆栈用于函数调用。这就是如果您在递归时不小心会收到“堆栈溢出”错误的原因。(不是双关语)。
如果这是真的,那么asmlinkage
GCC 指令有什么特别之处。
它说,来自#kernelnewbies
asmlinkage 标签是我们应该注意的关于这个简单函数的另一件事。这是一些 gcc 魔法的 #define,它告诉编译器该函数不应期望在寄存器中找到它的任何参数(一种常见的优化),而只能在 CPU 的堆栈上。
我的意思是我不认为寄存器用于正常的函数调用。
更奇怪的是,当你了解到它是在 x86 上使用 GCC regparm 函数属性实现的。
regparm的文档如下:
在 x86-32 目标上,如果参数在寄存器 EAX、EDX 和 ECX 中而不是在堆栈中是整数类型,则 regparm 属性会导致编译器将第一个参数传递给 number。
这基本上与asmlinkage
正在尝试做的相反。
那么会发生什么?它们是在堆栈上还是在寄存器上。
我哪里错了?
信息不是很清楚。
因为std::thread t(foo);
,有一个有意义foo [[noreturn]] () {...}
吗?对于前者 对于一个分离的线程(在应用程序完成之前用作一种守护进程)?
c++ ×6
gcc ×5
python ×3
c++11 ×2
clang ×2
attributes ×1
c ×1
const ×1
decorator ×1
function ×1
linux ×1
linux-kernel ×1
objective-c ×1
x86 ×1