IDDPM原理和代码剖析

这篇具有很好参考价值的文章主要介绍了IDDPM原理和代码剖析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

Improved Denoising Diffusion Probabilistic Models(IDDPM) 是上一篇 Denoising Diffusion Probabilistic Models(DDPM)的改进工作。
之前一些重要的公式已在上一篇博客 DDPM原理与代码剖析说过, 这里将不再赘述。本文主要将一些改进点和代码的解释。

本文参考视频 58、Improved Diffusion的PyTorch代码逐行深入讲解, up讲解得很清晰,推荐观看。

本文不断更新中ing…

DDIM针对采样进行了优化,利用respace技巧减少了采样步骤 DDIM原理及代码(Denoising diffusion implicit models)

复现这篇论文代码折腾了一下 Ubuntu 20.04下安装和配置MPI, 感谢这篇文章。
mpi4py这个库一直下不好原来是没有下mpicc。



代码

案例主要基于这份OpenAI官方代码 openai/improved-diffusion 。
该部分主要关注前向扩散,逆向扩散, 采样以及loss计算。至于模型用的是加了attention的unet,这里不展开。

主要集中于 improved_diffusion/gaussian_diffusion.py中的GaussianDiffusion类, 另外该部分只抽取核心部分代码,至于鲁棒性的,比如assert或者类型转换的代码将不包括,需要运行的请查看原仓库中的代码。

GaussianDiffusion

init

模型参数穿进来了betas, 其中betas是这么来的。原始的DDPM是采用Linear的方式,而IDDPM采用的是cosine的方式。

# gaussian_diffusion.py
def get_named_beta_schedule(schedule_name, num_diffusion_timesteps):
    """
    Get a pre-defined beta schedule for the given name.
    """
    if schedule_name == "linear":
        # Linear schedule from Ho et al, extended to work for any number of
        # diffusion steps.
        scale = 1000 / num_diffusion_timesteps
        beta_start = scale * 0.0001
        beta_end = scale * 0.02
        return np.linspace(
            beta_start, beta_end, num_diffusion_timesteps, dtype=np.float64
        )
    elif schedule_name == "cosine":
        return betas_for_alpha_bar(
            num_diffusion_timesteps,
            lambda t: math.cos((t + 0.008) / 1.008 * math.pi / 2) ** 2,
        )

alphas_cumprod 是 α ‾ t \overline{\alpha}_t αt, alphas_cumprod_prev 是 α ‾ t − 1 \overline{\alpha}_{t-1} αt1, alphas_cumprod_next 是 α ‾ t + 1 \overline{\alpha}_{t+1} αt+1

alphas = 1.0 - betas
alphas_cumprod = np.cumprod(alphas, axis=0)
alphas_cumprod_prev = np.append(1.0, self.alphas_cumprod[:-1])
alphas_cumprod_next = np.append(self.alphas_cumprod[1:], 0.0)

α ‾ t \sqrt{\overline{\alpha}_t} αt 为 sqrt_alphas_cumprod

sqrt_alphas_cumprod = np.sqrt(self.alphas_cumprod)

1 − α ‾ t \sqrt{1-\overline{\alpha}_t} 1αt 为 sqrt_one_minus_alphas_cumprod

sqrt_one_minus_alphas_cumprod = np.sqrt(1.0 - self.alphas_cumprod)

l o g ( 1 − α ‾ t ) log(1-\overline{\alpha}_t) log(1αt) 为 log_one_minus_alphas_cumprod。

log_one_minus_alphas_cumprod = np.log(1.0 - self.alphas_cumprod)

1 α ‾ t \frac{1}{\sqrt{\overline{\alpha}_t}} αt 1 为 sqrt_recip_alphas_cumprod

sqrt_recip_alphas_cumprod = np.sqrt(1.0 / self.alphas_cumprod)

1 α ‾ t − 1 \sqrt{\frac{1}{\overline{\alpha}_t}-1} αt11 为 sqrt_recipm1_alphas_cumprod

sqrt_recipm1_alphas_cumprod = np.sqrt(1.0 / self.alphas_cumprod - 1)

β ~ t = 1 − α ‾ t − 1 1 − α ‾ t β t \widetilde{\beta}_t = \frac{1-\overline{\alpha}_{t-1}}{1-\overline{\alpha}_t}\beta_t β t=1αt1αt1βt

# calculations for posterior q(x_{t-1} | x_t, x_0)
posterior_variance = (
   betas * (1.0 - self.alphas_cumprod_prev) / (1.0 - self.alphas_cumprod)
)

取一个log

# log calculation clipped because the posterior variance is 0 at the
# beginning of the diffusion chain.
posterior_log_variance_clipped = np.log(
   np.append(self.posterior_variance[1], self.posterior_variance[1:])
)

μ ~ ( X t , X 0 ) = α ‾ t − 1 1 − α ‾ t X 0 + α t ( 1 − α ‾ t − 1 ) 1 − α ‾ t X t \widetilde{\mu}(X_t, X_0) = \frac{\sqrt{\overline{\alpha}_{t-1}}}{1-\overline{\alpha}_t} X_0 + \frac{\sqrt{\alpha_t}(1-\overline{\alpha}_{t-1})}{1-\overline{\alpha}_{t}}X_t μ (Xt,X0)=1αtαt1 X0+1αtαt (1αt1)Xt, 其中 X 0 X_0 X0 前的系数对应 posterior_mean_coef1, X t X_t Xt 前的系数对应 posterior_mean_coef2。

posterior_mean_coef1 = (
    betas * np.sqrt(self.alphas_cumprod_prev) / (1.0 - self.alphas_cumprod)
)
posterior_mean_coef2 = (
   (1.0 - self.alphas_cumprod_prev)
   * np.sqrt(alphas)
   / (1.0 - self.alphas_cumprod)
)



q_mean_variance

传入 (x_start, t), 得到 均值和方差
q ( X t ∣ X 0 ) = N ( X t ; α ‾ t X 0 , ( 1 − α ‾ t ) I ) q(X_t|X_0) = N(X_t; \sqrt{\overline{\alpha}_t}X_0, (1-\overline{\alpha}_t)I) q(XtX0)=N(Xt;αt X0,(1αt)I)

mean = (
     _extract_into_tensor(self.sqrt_alphas_cumprod, t, x_start.shape) * x_start
)
variance = _extract_into_tensor(1.0 - self.alphas_cumprod, t, x_start.shape)
log_variance = _extract_into_tensor(
   self.log_one_minus_alphas_cumprod, t, x_start.shape
)

q_sample

重参数化获取加噪后的图片
X t = α ‾ t X 0 + 1 − α ‾ t   ϵ X_t = \sqrt{\overline{\alpha}_t}X_0+\sqrt{1-\overline{\alpha}_t}~\epsilon Xt=αt X0+1αt  ϵ

_extract_into_tensor(self.sqrt_alphas_cumprod, t, x_start.shape) * x_start
+ _extract_into_tensor(self.sqrt_one_minus_alphas_cumprod, t, x_start.shape)
* noise



q_posterior_mean_variance

后验的均值和分布
μ ~ ( X t , X 0 ) = α ‾ t − 1 1 − α ‾ t X 0 + α t ( 1 − α ‾ t − 1 ) 1 − α ‾ t X t \widetilde{\mu}(X_t, X_0) = \frac{\sqrt{\overline{\alpha}_{t-1}}}{1-\overline{\alpha}_t} X_0 + \frac{\sqrt{\alpha_t}(1-\overline{\alpha}_{t-1})}{1-\overline{\alpha}_{t}}X_t μ (Xt,X0)=1αtαt1 X0+1αtαt (1αt1)Xt

posterior_mean = (
            _extract_into_tensor(self.posterior_mean_coef1, t, x_t.shape) * x_start
            + _extract_into_tensor(self.posterior_mean_coef2, t, x_t.shape) * x_t
        )

β ~ t = 1 − α ‾ t − 1 1 − α ‾ t β t \widetilde{\beta}_t = \frac{1-\overline{\alpha}_{t-1}}{1-\overline{\alpha}_t} \beta_t β t=1αt1αt1βt, 这个之前 init 函数中已经算出来了,就不需要再计算了

posterior_variance = _extract_into_tensor(self.posterior_variance, t, x_t.shape)



p_mean_variance

这里传入的是 t t t 时刻的x, 要预测 t − 1 t-1 t1 时刻的 均值mean 和方差variance。
方差既可以学习,也可以固定值。
(1) 方差可学习, 及下面的条件

if self.model_var_type in [ModelVarType.LEARNED, ModelVarType.LEARNED_RANGE]:

需要在channel维度切分一下

model_output, model_var_values = th.split(model_output, C, dim=1)

这里也分两种情况,原始DDPM是直接预测方差

if self.model_var_type == ModelVarType.LEARNED:
	  model_log_variance = model_var_values
	  model_variance = th.exp(model_log_variance)

而improve-DDPM中是预测范围, 及预测下列式子的v。
Σ θ ( X t , t ) = e x p ( v l o g β t + ( 1 − v ) l o g β ~ t ) \Sigma_{\theta}(X_t, t)=exp(vlog\beta_t + (1-v)log \widetilde{\beta}_t) Σθ(Xt,t)=exp(vlogβt+(1v)logβ t)

因为 β ~ t = 1 − α ‾ t − 1 1 − α ‾ t β t \widetilde{\beta}_t = \frac{1-\overline{\alpha}_{t-1}}{1-\overline{\alpha}_t} \beta_t β t=1αt1αt1βt, 而 1 − α ‾ t − 1 < 1 − α ‾ t 1-\overline{\alpha}_{t-1} < 1-\overline{\alpha}_t 1αt1<1αt, 所以 β ~ t < β t \widetilde{\beta}_t < \beta_t β t<βt

故 max_log 就是 l o g β t log \beta_t logβt

max_log = _extract_into_tensor(np.log(self.betas), t, x.shape)

而 min_log 就是 l o g β ~ t log \widetilde{\beta}_t logβ t

min_log = _extract_into_tensor(
                    self.posterior_log_variance_clipped, t, x.shape)

将预测值 [-1, 1] 转化为 [0, 1]

# The model_var_values is [-1, 1] for [min_var, max_var].
frac = (model_var_values + 1) / 2

然后根据公式 Σ θ ( X t , t ) = e x p ( v l o g β t + ( 1 − v ) l o g β ~ t ) \Sigma_{\theta}(X_t, t)=exp(vlog\beta_t + (1-v)log \widetilde{\beta}_t) Σθ(Xt,t)=exp(vlogβt+(1v)logβ t)

model_log_variance = frac * max_log + (1 - frac) * min_log
model_variance = th.exp(model_log_variance)



(2) 方差不可学习
在DDPM中是用 β t \beta_t βt, 而在IDDPM中有两种方式 β t \beta_t βt or β ~ t \widetilde{\beta}_t β t
大的方差即 β t \beta_t βt,

ModelVarType.FIXED_LARGE: (
    # for fixedlarge, we set the initial (log-)variance like so
    # to get a better decoder log likelihood.
    np.append(self.posterior_variance[1], self.betas[1:]),
    np.log(np.append(self.posterior_variance[1], self.betas[1:])),
),

小的方差即 β ~ t \widetilde{\beta}_t β t

ModelVarType.FIXED_SMALL: (
    self.posterior_variance,
    self.posterior_log_variance_clipped,
),

注意上面计算的输出是列表,然后我们只需要取出第 t 时刻的

model_variance = _extract_into_tensor(model_variance, t, x.shape)
model_log_variance = _extract_into_tensor(model_log_variance, t, x.shape)

然后就是对均值的预测
(1) 预测 X t − 1 X_{t-1} Xt1 时刻的均值

if self.model_mean_type == ModelMeanType.PREVIOUS_X:

那么直接

model_mean = model_output

这里顺带还预测除了 X 0 X_0 X0, 在训练中不会用到,但在evaluation中会用到

pred_xstart = process_xstart(
    self._predict_xstart_from_xprev(x_t=x, t=t, xprev=model_output)
)



(2) 预测 X 0 X_0 X0

if self.model_mean_type == ModelMeanType.START_X:

经过一个后处理函数即可

pred_xstart = process_xstart(model_output)



(3) 预测 噪声

ModelMeanType.EPSILON
pred_xstart = process_xstart(
   self._predict_xstart_from_eps(x_t=x, t=t, eps=model_output)
)

μ ~ ( X t , X 0 ) = α ‾ t − 1 1 − α ‾ t X 0 + α t ( 1 − α ‾ t − 1 ) 1 − α ‾ t X t \widetilde{\mu}(X_t, X_0) = \frac{\sqrt{\overline{\alpha}_{t-1}}}{1-\overline{\alpha}_t} X_0 + \frac{\sqrt{\alpha_t}(1-\overline{\alpha}_{t-1})}{1-\overline{\alpha}_{t}}X_t μ (Xt,X0)=1αtαt1 X0+1αtαt (1αt1)Xt

model_mean, _, _ = self.q_posterior_mean_variance(
   x_start=pred_xstart, x_t=x, t=t
)



_predict_xstart_from_xprev

利用该公式计算 X 0 X_0 X0: μ ~ ( X t , X 0 ) = α ‾ t − 1 1 − α ‾ t X 0 + α t ( 1 − α ‾ t − 1 ) 1 − α ‾ t X t \widetilde{\mu}(X_t, X_0) = \frac{\sqrt{\overline{\alpha}_{t-1}}}{1-\overline{\alpha}_t} X_0 + \frac{\sqrt{\alpha_t}(1-\overline{\alpha}_{t-1})}{1-\overline{\alpha}_{t}}X_t μ (Xt,X0)=1αtαt1 X0+1αtαt (1αt1)Xt

return (  # (xprev - coef2*x_t) / coef1
    _extract_into_tensor(1.0 / self.posterior_mean_coef1, t, x_t.shape) * xprev 
    - _extract_into_tensor(
       self.posterior_mean_coef2 / self.posterior_mean_coef1, t, x_t.shape
    )
    * x_t
)



_predict_xstart_from_eps

X 0 = 1 α t ( X t − β t 1 − α ‾ t ϵ ) X_0 = \frac{1}{\sqrt{\alpha_t}}(X_t-\frac{\beta_t}{\sqrt{1-\overline{\alpha}_t}}\epsilon) X0=αt 1(Xt1αt βtϵ)
将上述公式化简
X 0 = 1 α ‾ t X t − 1 α ‾ t − 1   ϵ X_0 = \frac{1}{\sqrt{\overline{\alpha}_t}}X_t - \sqrt{\frac{1}{\overline{\alpha}_t}-1}~\epsilon X0=αt 1Xtαt11  ϵ

_extract_into_tensor(self.sqrt_recip_alphas_cumprod, t, x_t.shape) * x_t
- _extract_into_tensor(self.sqrt_recipm1_alphas_cumprod, t, x_t.shape) * eps



p_sample

基于 X t X_t Xt 采样出 X t − 1 X_{t-1} Xt1
out是 { “mean”: model_mean, “variance”: model_variance, “log_variance”: model_log_variance, “pred_xstart”: pred_xstart}

# 得到 X[t-1]的均值、方差、对数方差、X[0]的预测值
out = self.p_mean_variance(
          model,
          x,
          t,
          clip_denoised=clip_denoised,
          denoised_fn=denoised_fn,
          model_kwargs=model_kwargs,
      )

重参数化采样

noise = th.randn_like(x)
sample = out["mean"] + nonzero_mask * th.exp(0.5 * out["log_variance"]) * noise

p_sample_loop 和 p_sample_loop_progressive 函数迭代调用这个函数。



p_sample_loop_progressive

X 0 X_0 X0

if noise is not None:
   img = noise
else:
   img = th.randn(*shape, device=device)

T, T-1, …, 0

indices = list(range(self.num_timesteps))[::-1]

不断的采样

for i in indices:
    t = th.tensor([i] * shape[0], device=device)
    with th.no_grad():
        out = self.p_sample(
                model,
                img,
                t,
                clip_denoised=clip_denoised,
                denoised_fn=denoised_fn,
                model_kwargs=model_kwargs,
             )
        yield out
        img = out["sample"]



_vb_terms_bpd

vb 变分下界, bpd 是 bit per dimension

算出 q 分布真实的均值和方差

true_mean, _, true_log_variance_clipped = self.q_posterior_mean_variance(
     x_start=x_start, x_t=x_t, t=t
)

算出 p 分布的模型预测的均值和方差

out = self.p_mean_variance(
           model, x_t, t, clip_denoised=clip_denoised, model_kwargs=model_kwargs
)

计算两个高斯分布的KL散度。
L t − 1 = D K L ( q ( X t − 1 ∣ X t , X 0 )   ∣ ∣   p θ ( X t − 1 ∣ X t ) ) L_{t-1} = D_{KL}(q(X_{t-1}|X_t, X_0)~||~ p_\theta (X_{t-1}|X_t)) Lt1=DKL(q(Xt1Xt,X0) ∣∣ pθ(Xt1Xt))

kl = normal_kl( true_mean, true_log_variance_clipped, 
                out["mean"], out["log_variance"])
kl = mean_flat(kl) / np.log(2.0)



L 0 = − l o g p θ ( X 0 ∣ X 1 ) L_0=-log p_{\theta}(X_0|X_1) L0=logpθ(X0X1)
用一个累计函数的差分模拟一个离散分布

decoder_nll = -discretized_gaussian_log_likelihood(
    x_start, means=out["mean"], log_scales=0.5 * out["log_variance"]
)
decoder_nll = mean_flat(decoder_nll) / np.log(2.0)

合并一下, 囊括所有时刻的KL散度

output = th.where((t == 0), decoder_nll, kl)



discretized_gaussian_log_likelihood

improved_diffusion/losses.py

def discretized_gaussian_log_likelihood(x, *, means, log_scales):
    """
    Compute the log-likelihood of a Gaussian distribution discretizing to a
    given image.

    :param x: the target images. It is assumed that this was uint8 values,
              rescaled to the range [-1, 1].
    :param means: the Gaussian mean Tensor.
    :param log_scales: the Gaussian log stddev Tensor.
    :return: a tensor like x of log probabilities (in nats).
    """
    assert x.shape == means.shape == log_scales.shape
    centered_x = x - means
    inv_stdv = th.exp(-log_scales)
    plus_in = inv_stdv * (centered_x + 1.0 / 255.0)
    cdf_plus = approx_standard_normal_cdf(plus_in)
    min_in = inv_stdv * (centered_x - 1.0 / 255.0)
    cdf_min = approx_standard_normal_cdf(min_in)
    log_cdf_plus = th.log(cdf_plus.clamp(min=1e-12))
    log_one_minus_cdf_min = th.log((1.0 - cdf_min).clamp(min=1e-12))
    cdf_delta = cdf_plus - cdf_min
    log_probs = th.where(
        x < -0.999,
        log_cdf_plus,
        th.where(x > 0.999, log_one_minus_cdf_min, th.log(cdf_delta.clamp(min=1e-12))),
    )
    assert log_probs.shape == x.shape
    return log_probs



training_losses

如果losstype是KL的话

if self.loss_type == LossType.KL or self.loss_type == LossType.RESCALED_KL:

调用之前的 vb_terms 函数

terms["loss"] = self._vb_terms_bpd(
                model=model,
                x_start=x_start,
                x_t=x_t,
                t=t,
                clip_denoised=False,
                model_kwargs=model_kwargs,
            )["output"]



至于MSE loss则根据模型预测类型不同加以不同的判断

elif self.loss_type == LossType.MSE or self.loss_type == LossType.RESCALED_MSE:

(1) 如果模型预测的是方差

if self.model_var_type in [
    ModelVarType.LEARNED,
    ModelVarType.LEARNED_RANGE,
]:

拆分开,model_output 和 model_var_values

B, C = x_t.shape[:2]
assert model_output.shape == (B, C * 2, *x_t.shape[2:])
model_output, model_var_values = th.split(model_output, C, dim=1)
frozen_out = th.cat([model_output.detach(), model_var_values], dim=1)
terms["vb"] = self._vb_terms_bpd(
	model=lambda *args, r=frozen_out: r,
	x_start=x_start,
	x_t=x_t,
	t=t,
	clip_denoised=False,
)["output"]

这里由于model已经预测过一回了,就不用再让模型预测一回,所以传入的model直接就是一个恒等返回。这里 frozen_out 是让方差的学习不影响均值的优化。

model=lambda *args, r=frozen_out: r

这里 lambda相当于一个匿名函数

def fun(*args, r=frozen_out):
	return r

如果rescale的话,

if self.loss_type == LossType.RESCALED_MSE:
    # Divide by 1000 for equivalence with initial implementation.
    # Without a factor of 1/1000, the VB term hurts the MSE term.
    terms["vb"] *= self.num_timesteps / 1000.0

接下来就看目标预测的是哪种了
可以是 X t − 1 X_{t-1} Xt1 时刻的均值和方差, X 0 X_0 X0, 也可以是噪声

target = {
            ModelMeanType.PREVIOUS_X: self.q_posterior_mean_variance(
                x_start=x_start, x_t=x_t, t=t
            )[0],
            ModelMeanType.START_X: x_start,
            ModelMeanType.EPSILON: noise,
          }[self.model_mean_type]

然后就算个MSEloss即可

terms["mse"] = mean_flat((target - model_output) ** 2)

再把loss合起来

if "vb" in terms:
    terms["loss"] = terms["mse"] + terms["vb"]
else:
    terms["loss"] = terms["mse"]

总之,当方差可学习的话,就会有 vb 这一项损失。文章来源地址https://www.toymoban.com/news/detail-440489.html

到了这里,关于IDDPM原理和代码剖析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 掌握 GitHub Copilot:6个代码自动补全的必备技巧前言

    GitHub Copilot 是一款由人工智能驱动的编码助手,它能够根据上下文提供代码建议,极大地加快了开发过程。在之前介绍如何激活 Copilot 的文章之后,本文将深入探讨六个关键技巧,以高效利用 GitHub Copilot。 通过以下快捷键,可以更高效地使用 GitHub Copilot: **Tab:**接受建议。

    2024年04月16日
    浏览(77)
  • Flutter原理篇:GestureDetector原理深度剖析及手势原理(上)

    今天我们来讲讲GestureDetector的深度剖析,只有了解原理了,才能知道手势冲突如何解决以及如何更灵活的运用手势。 我们先来看看GestureDetector的内部结构 1. GestureDetector 只是一个包装类,最终还是由 Listener 的 RenderPointListener 执行事件的操作 2.点击事件开始时会首先执行 RawG

    2024年04月27日
    浏览(36)
  • Hbase基本原理剖析

    数据存储使用HBase来承接,HBase是一个开源的、面向列(Column-Oriented)、适合存储海量非结构化数据或半结构化数据的、具备高可靠性、高性能、可灵活扩展伸缩的、支持实时数据读写的分布式存储系统。更多关于HBase的信息,请参见:https://hbase.apache.org/。 存储在HBase中的表的

    2024年02月16日
    浏览(42)
  • Elasticsearch原理剖析

    Elasticsearch集群方案由EsMaster、EsClient和EsNode1、EsNode2、EsNode3、EsNode4、EsNode5、EsNode6、EsNode7、EsNode8、EsNode9进程组成,如下图所示,模块说明如表下所示。 说明如表: 名称 说明 Client Client使用HTTP或HTTPS协议同Elasticsearch集群中的EsClient以及各EsNode实例进程进行通信,进行分布式索

    2024年02月17日
    浏览(39)
  • Hive原理剖析

    Hive是建立在Hadoop上的数据仓库框架,提供大数据平台批处理计算能力,能够对结构化/半结构化数据进行批量分析汇总完成数据计算。提供类似SQL的Hive Query Language语言操作结构化数据,其基本原理是将HQL语言自动转换成MapReduce任务,从而完成对Hadoop集群中存储的海量数据进行

    2024年02月10日
    浏览(16)
  • IoTDB原理剖析

    IoTDB(物联网数据库)是一体化收集、存储、管理与分析物联网时序数据的软件系统。 Apache IoTDB采用轻量式架构,具有高性能和丰富的功能。 IoTDB从存储上对时间序列进行排序,索引和chunk块存储,大大的提升时序数据的查询性能。通过Raft协议,来确保数据的一致性。针对时

    2024年02月13日
    浏览(33)
  • ChatGPT原理剖析

    由开发者 准备好的罐头 回应: 下面是一个问答,让ChatGPT讲一个关于人工智慧的笑话,但可以看出来,这个笑话的笑点显然和我们平常人不太一样,显得笑点非常奇怪: 你搜寻之后,ChatGPT从网上搜寻答案, 整理重组 给你想要的答案: 但实际上,多数ChatGPT的答案在网络上都

    2023年04月09日
    浏览(35)
  • Flink基本原理剖析讲解

    Flink是一个批处理和流处理结合的统一计算框架,其核心是一个提供了数据分发以及并行化计算的流数据处理引擎。它的最大亮点是流处理,是业界最顶级的开源流处理引擎。 Flink最适合的应用场景是低时延的数据处理(Data Processing)场景:高并发pipeline处理数据,时延毫秒级

    2024年02月16日
    浏览(37)
  • HDFS原理剖析

    HDFS是Hadoop的分布式文件系统(Hadoop Distributed File System),实现大规模数据可靠的分布式读写。HDFS针对的使用场景是数据读写具有“一次写,多次读”的特征,而数据“写”操作是顺序写,也就是在文件创建时的写入或者在现有文件之后的添加操作。HDFS保证一个文件在一个时

    2024年02月12日
    浏览(27)
  • ptmalloc底层原理剖析

    目录 一、概述 二、基础了解 2.1 32位进程默认内存布局 2.2 brk  sbrk  mmap 三、内存管理 2.1 结构 2.1.1 main_area 与 non_main_area 2.1.2 malloc_chunk 2.1.3 空闲链表bins 2.1.4 初始化 2.2 内存分配与释放 2.3 使用注意 三、ptmalloc、tcmalloc与jemalloc实现机制对比分析 ptmalloc是开源 GNU C Library (gli

    2024年02月16日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包