令人困惑的return by value (转)

令人困惑的return by value (转)[@more@]

 

问题从这里开始。
class X;
const X operator+( const X& x1, const X& x2 );
X foo()
{
return X(a+b);
}

X foo()
{
X xx(a+b);
return xx;
}
这两个函数,有什么区别?
这个问题牵涉到C++的内部处理,下面是其更通用的模式
X foo()
{
X xx;
// process
...
return xx;
}
C++如何处理return by value,传统的方法是修改函数原型。
void foo( X& r )
{
X xx;
xx.X(); //ctor
// process
...
r.XX( xx ) // copy ctor
}
这样就把xx的值给返回了,这里有一个xx的临时对象的ctor和dtor。
于是乎。
X obj = foo();
被转化为 
X obj;
foo( obj );
但是,对于程序员来说,是可以进行一些优化的,其方法就是采用ctor返回,
X foo()
{
return X( ... );
}

编译器处理过后,为这样。
void foo( X &r )
{
return r.X(...);
}
看出来了吗?这里少个对象(即上面的xx)的ctor和dtor,效率自然提高。
更进一步,如果这个函数是inline的,则
X obj = foo();
被处理成
X obj;
obj.X(...);
Bingo!!
真的是棒呆了,C++注重的效率得以完全体现。
这种优化我称之为ARV( anonymous return value )优化,:)
然而对于前者NRV( named return value ),我们又该如何呢?
答案是:没有办法,唯一可作的是期待编译器给我们一些帮助。
如果我们的编译器够power的话,那么
X foo()
{
X xx;
// process
...
return xx;
}
可能被处理成:
void foo( X &r )
{
// ctor
r.X();
// process
...
}
在这里,同样没有出现named object(指xx)的ctor和dtor,但是作为一个应该把握全局的程序员,我劝你不要太指望它。
首先,它还是调用了default ctor,这在ARV中是不存在的。
其次,你无法知道编译器是否正在这样做,毕竟对于厂家来说,它有这样的权利不让你知道细节。
再次,编译器就算有这样的能力,但仅仅对一些简单的函数有效,而对于实际编程来说,函数往往很复杂,
比如具有多个分支返回的函数,编译器就只能叹气了。
还有,在函数开头就声明对象的作法,可不是正宗C++的style,C++一向提倡“只有在必要是才使用”,真正的C++程序员应该牢记这一点。
最后,从C++编译器历史来看,在优化过程中,匿名对象比命名对象更容易消除,你要充分利用它。
答案:
对于这么一个简单的函数,如果你的编译器支持NRV优化,则结果是一样的,否则。。。
而ARV优化总是支持的。
那采用ARV这样做有没有缺点呢?
或许吧,毕竟你要写一堆ctor用于特殊用途了。:)
注:
本文中的例子选自<ide C++ Object Model>>,要感谢Lippman给C++程序员们写了这么一本好书,同样感谢JJhou给中国程序员的翻译。
本文还参考了MEC(More Effective C++)


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10790690/viewspace-971095/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10790690/viewspace-971095/

### Transformer Decoder 的代码实现 以下是基于 PyTorch 实现的一个完整的 Transformer 解码器 (Decoder) 示例: ```python import torch import torch.nn as nn from torch.autograd import Variable class PositionalEncoding(nn.Module): def __init__(self, d_model, max_len=5000): super(PositionalEncoding, self).__init__() pe = torch.zeros(max_len, d_model) position = torch.arange(0, max_len).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2) * -(torch.log(torch.tensor(10000.0)) / d_model)) pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term) pe = pe.unsqueeze(0) self.register_buffer('pe', pe) def forward(self, x): x = x + Variable(self.pe[:, :x.size(1)], requires_grad=False) return x class MultiHeadAttention(nn.Module): def __init__(self, heads, d_model, dropout=0.1): super(MultiHeadAttention, self).__init__() assert d_model % heads == 0 self.d_k = d_model // heads self.heads = heads self.linears = clones(nn.Linear(d_model, d_model), 4) self.attn = None self.dropout = nn.Dropout(p=dropout) def attention(self, query, key, value, mask=None, dropout=None): scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(self.d_k) if mask is not None: scores = scores.masked_fill(mask == 0, -1e9) p_attn = F.softmax(scores, dim=-1) if dropout is not None: p_attn = dropout(p_attn) return torch.matmul(p_attn, value), p_attn def forward(self, query, key, value, mask=None): nbatches = query.size(0) query, key, value = \ [l(x).view(nbatches, -1, self.heads, self.d_k).transpose(1, 2) for l, x in zip(self.linears, (query, key, value))] x, self.attn = self.attention(query, key, value, mask=mask, dropout=self.dropout) x = x.transpose(1, 2).contiguous().view(nbatches, -1, self.heads * self.d_k) return self.linears[-1](x) def clones(module, N): "Produce N identical layers." return nn.ModuleList([copy.deepcopy(module) for _ in range(N)]) class SublayerConnection(nn.Module): """ A residual connection followed by a layer norm. Note for code simplicity the norm is first as opposed to last. """ def __init__(self, size, dropout): super(SublayerConnection, self).__init__() self.norm = nn.LayerNorm(size) self.dropout = nn.Dropout(dropout) def forward(self, x, sublayer): "Apply residual connection to any sublayer with the same size." return x + self.dropout(sublayer(self.norm(x))) class DecoderLayer(nn.Module): "Decoder is made of self-attn, src-attn, and feed forward" def __init__(self, size, self_attn, src_attn, feed_forward, dropout): super(DecoderLayer, self).__init__() self.size = size self.self_attn = self_attn self.src_attn = src_attn self.feed_forward = feed_forward self.sublayer = clones(SublayerConnection(size, dropout), 3) def forward(self, x, memory, src_mask, tgt_mask): m = memory x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, tgt_mask)) x = self.sublayer[1](x, lambda x: self.src_attn(x, m, m, src_mask)) return self.sublayer[2](x, self.feed_forward) class Generator(nn.Module): "Define standard linear + softmax generation step." def __init__(self, d_model, vocab): super(Generator, self).__init__() self.proj = nn.Linear(d_model, vocab) def forward(self, x): return torch.log_softmax(self.proj(x), dim=-1) class Decoder(nn.Module): "Generic N layer decoder with masking." def __init__(self, layer, N): super(Decoder, self).__init__() self.layers = clones(layer, N) self.norm = nn.LayerNorm(layer.size) def forward(self, x, memory, src_mask, tgt_mask): for layer in self.layers: x = layer(x, memory, src_mask, tgt_mask) return self.norm(x) ``` 上述代码实现了 Transformer 中的解码器部分,包括多头注意力机制、前馈神经网络以及位置编码等功能模块[^1][^2][^3][^4][^5]。 #### 关键组件说明: - **Positional Encoding**: 提供序列中的相对或绝对位置信息。 - **Multi-head Attention**: 自注意力机制的核心组成部分,允许模型关注输入的不同子空间特征。 - **Sub-layer Connection & Normalization**: 使用残差连接和层归一化提升模型性能并加速收敛。 - **Feed Forward Network**: 每个解码器层内部的标准全连接前向传播网络。 - **Decoder Layer**: 结合自注意力机制、源注意力机制和前馈网络构建单个解码器层。 - **Generator**: 将解码器输出映射到词汇表大小的空间上,并计算概率分布。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值