循环缓冲区 【ChatGPT】

简介: 循环缓冲区 【ChatGPT】

循环缓冲区

作者:

Linux提供了许多功能,可用于实现循环缓冲区。有两组这样的功能:

  1. 用于确定2的幂大小缓冲区信息的便利函数。
  2. 当缓冲区中的对象的生产者和消费者不想共享锁时,使用内存屏障。

要使用下面讨论的这些功能,只需要一个生产者和一个消费者。可以通过串行化来处理多个生产者,并通过串行化来处理多个消费者。

什么是循环缓冲区?

首先,什么是循环缓冲区?循环缓冲区是一个固定大小的缓冲区,其中有两个索引:

  • '头'索引 - 生产者将项目插入缓冲区的位置。
  • '尾'索引 - 消费者在缓冲区中找到下一个项目的位置。

通常情况下,当尾指针等于头指针时,缓冲区为空;当头指针比尾指针小1时,缓冲区为满。

当添加项目时,头索引会递增,而当移除项目时,尾索引会递增。尾索引不应超过头索引,并且当它们到达缓冲区末尾时,两个索引都应该被包装到0,从而允许无限量的数据流经过缓冲区。

通常,项目都是相同的单位大小,但并不严格要求使用下面的技术。如果要在缓冲区中包含多个项目或大小可变的项目,则可以逐渐增加索引,前提是两个索引都不会超过对方。但是,实施者必须小心,因为一个大于一个单位大小的区域可能会包装到缓冲区的末尾,并被分成两个段。

测量2的幂缓冲区

通常情况下,计算任意大小的循环缓冲区的占用量或剩余容量将是一个缓慢的操作,需要使用模数(除法)指令。但是,如果缓冲区的大小是2的幂,则可以使用更快的按位AND指令。

Linux提供了一组用于处理2的幂循环缓冲区的宏。可以通过以下方式使用这些宏:

#include <linux/circ_buf.h>

这些宏包括:

  • 测量缓冲区中剩余的空间:
CIRC_SPACE(head_index, tail_index, buffer_size);
  • 这将返回缓冲区中剩余的空间,可以插入项目。
  • 测量缓冲区中最大的连续空间:
CIRC_SPACE_TO_END(head_index, tail_index, buffer_size);
  • 这将返回缓冲区中最大的连续空间,可以立即插入项目,而无需回到缓冲区的开头。
  • 测量缓冲区的占用量:
CIRC_CNT(head_index, tail_index, buffer_size);
  • 这将返回当前占用缓冲区的项目数。
  • 测量缓冲区中不会包装的占用量:
CIRC_CNT_TO_END(head_index, tail_index, buffer_size);
  • 这将返回可以从缓冲区中提取的连续项目数,而无需回到缓冲区的开头。

这些宏中的每一个通常会返回一个介于0和buffer_size-1之间的值,但是:

  • CIRC_SPACE*() 用于生产者。对于生产者,它们将返回一个下限,因为生产者控制头索引,但是消费者可能仍在另一个CPU上耗尽缓冲区并移动尾索引。
  • 对于消费者,它将显示一个上限,因为生产者可能正在忙于耗尽空间。
  • CIRC_CNT*() 用于消费者。对于消费者,它们将返回一个下限,因为消费者控制尾索引,但是生产者可能仍在另一个CPU上填充缓冲区并移动头索引。
  • 对于生产者,它将显示一个上限,因为消费者可能正在忙于清空缓冲区。
  • 对于第三方,无法保证生产者和消费者对索引的写入的可见性顺序,因为它们是独立的,可能在不同的CPU上进行 - 因此,在这种情况下的结果只是一个猜测,甚至可能是负数。

使用内存屏障与循环缓冲区

通过在循环缓冲区中使用内存屏障,可以避免以下需求:

  • 使用单个锁来管理对缓冲区两端的访问,从而允许缓冲区同时被填充和清空。
  • 使用原子计数操作。

这有两个方面:填充缓冲区的生产者和清空缓冲区的消费者。在任何时候,只应该有一件事在填充缓冲区,而只应该有一件事在清空缓冲区,但是两个方面可以同时操作。

生产者

生产者将类似于以下内容:

spin_lock(&producer_lock);
unsigned long head = buffer->head;
/* spin_unlock() 和下一个 spin_lock() 提供所需的排序。 */
unsigned long tail = READ_ONCE(buffer->tail);
if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
/* 将一个项目插入缓冲区 */
struct item *item = buffer[head];
        produce_item(item);
        smp_store_release(buffer->head,
                          (head + 1) & (buffer->size - 1));
/* wake_up() 确保在唤醒任何人之前,头部已经提交 */
        wake_up(consumer);
}
spin_unlock(&producer_lock);

这将指示CPU必须在将新项目的内容写入之前,将头索引使其对消费者可用,并且指示CPU必须在唤醒消费者之前,必须写入修订后的头索引。

请注意,wake_up() 不会保证任何类型的屏障,除非实际唤醒了某些内容。因此,我们不能依赖它进行排序。但是,数组中始终会留下一个元素为空。因此,生产者必须在可能损坏消费者当前正在读取的元素之前产生两个元素。因此,在连续调用消费者之间的解锁-锁对提供了所需的排序,用于指示消费者已经空出了给定元素的索引的读取,以及生产者对该相同元素的写入。

消费者

消费者将类似于以下内容:

spin_lock(&consumer_lock);
/* 在读取该索引的内容之前读取索引。 */
unsigned long head = smp_load_acquire(buffer->head);
unsigned long tail = buffer->tail;
if (CIRC_CNT(head, tail, buffer->size) >= 1) {
/* 从缓冲区中提取一个项目 */
struct item *item = buffer[tail];
        consume_item(item);
/* 在增加尾部之前完成读取描述符。 */
        smp_store_release(buffer->tail,
                          (tail + 1) & (buffer->size - 1));
}
spin_unlock(&consumer_lock);

这将指示CPU在读取新项目之前,必须确保索引是最新的,然后必须确保CPU在写入新尾指针之前已经完成了读取项目,这将擦除该项目。

请注意,使用READ_ONCE() 和smp_load_acquire() 读取对立索引。这可以防止编译器丢弃并重新加载其缓存的值。如果可以确保对立索引只会被使用一次,则不严格需要这样做。此外,smp_load_acquire() 还强制CPU对后续内存引用进行排序。类似地,两个算法中都使用了smp_store_release() 来写入线程的索引。这说明了我们正在写入可以同时被读取的内容,防止编译器破坏存储,并强制对先前的访问进行排序。

进一步阅读

另请参阅Documentation/memory-barriers.txt,了解Linux的内存屏障功能的描述。

本文来自博客园,作者:摩斯电码,未经同意,禁止

相关文章
|
存储 缓存 API
DMA-BUF缓冲区共享和同步【ChatGPT】
DMA-BUF缓冲区共享和同步【ChatGPT】
|
8月前
|
机器学习/深度学习 数据采集 人工智能
从ChatGPT到文心一言:AI为什么能“懂人话”?——大语言模型的底层逻辑揭秘
从ChatGPT到文心一言:AI为什么能“懂人话”?——大语言模型的底层逻辑揭秘
1106 9
|
人工智能 Linux API
Omnitool:开发者桌面革命!开源神器一键整合ChatGPT+Stable Diffusion等主流AI平台,本地运行不联网
Omnitool 是一款开源的 AI 桌面环境,支持本地运行,提供统一交互界面,快速接入 OpenAI、Stable Diffusion、Hugging Face 等主流 AI 平台,具备高度扩展性。
1740 94
Omnitool:开发者桌面革命!开源神器一键整合ChatGPT+Stable Diffusion等主流AI平台,本地运行不联网
|
11月前
|
传感器 存储 人工智能
ChatGPT让AI展现‘智能’魅力,函数调用和RAG如何助力迈向AI Agent?
本文由AI产品专家三桥君探讨了AI从被动响应到主动决策的演进路径,重点分析了函数调用和RAG技术在构建AI Agent中的关键作用。文章梳理了大模型能力的迭代(原生能力与涌现能力),技术演进的三个阶段(提示工程→函数调用→RAG),并提出AI Agent需具备环境感知、推理决策和行动执行的核心要素。AI产品专家三桥君认为,未来AGI需突破跨领域学习、实时更新和安全性挑战,最终实现如"贾维斯"般的智能伙伴。
398 1
ChatGPT让AI展现‘智能’魅力,函数调用和RAG如何助力迈向AI Agent?
|
11月前
|
机器学习/深度学习 人工智能 文字识别
浏览器AI模型插件下载,支持chatgpt、claude、grok、gemini、DeepSeek等顶尖AI模型!
极客侧边栏是一款浏览器插件,集成ChatGPT、Claude、Grok、Gemini等全球顶尖AI模型,支持网页提问、文档分析、图片生成、智能截图、内容总结等功能。无需切换页面,办公写作效率倍增。内置书签云同步与智能整理功能,管理更高效。跨平台使用,安全便捷,是AI时代必备工具!
874 8
|
机器学习/深度学习 人工智能 搜索推荐
哈佛推出全新类ChatGPT癌症诊断AI,登上Nature!准确率高达96%
哈佛大学研究团队开发的新型AI模型CHIEF,在《自然》期刊发表,癌症诊断准确率达96%。CHIEF基于深度学习,能自动识别、分类癌症并预测生存期,具高准确性、多任务能力和泛化性。它结合病理图像与基因组学等数据,显著提升诊断效率和个性化治疗水平,有望改善医疗资源不平等。但数据隐私和临床效果验证仍是挑战。论文见:https://www.nature.com/articles/s41586-024-07894-z
669 101
|
人工智能 编解码 运维
当ChatGPT能写情书、Sora会造电影:我们必须掌握的AI内容识别技能
随着AI技术迅猛发展,AI生成内容在文学、新闻、绘画等领域广泛应用,但其真假难辨、质量参差不齐,可能带来信息误导、知识产权侵犯及安全风险等问题。学会识别AI生成内容至关重要,包括通过逻辑漏洞排查、语言风格分析、生物特征异常检测等手段审核文本、图片和视频。人工审核在面对高隐蔽性内容时仍不可替代,需结合工具与上下文理解共同筑起防护屏障。守护真实信息、规避风险,是每个人在AI时代应尽的责任。
487 7
|
存储 人工智能 API
ChatGPT-on-WeChat:Star32.4k, DeepSeek加持!这款开源神器秒变AI助手,聊天体验直接起飞!
嗨,大家好,我是小华同学。今天为大家介绍一款结合DeepSeek引擎的开源项目——ChatGPT-on-WeChat,由开发者zhayujie打造。它将微信变成智能AI助手,支持文本、图片、语音对话,具备定时提醒、天气查询等扩展功能,完全开源且易于定制。项目地址:https://github.com/zhayujie/chatgpt-on-wechat。关注我们,获取更多优质开源项目和高效学习方法。
1903 11
|
人工智能 自然语言处理 算法
DeepSeek vs ChatGPT:AI对决中的赢家是……人类吗?
DeepSeek VS ChatGPT:DeepSeek以开源黑马姿态崛起,凭借低成本、高性能的「DeepSeek-V3」和专为深度推理设计的「DeepSeek-R1」,成为中小开发者的首选。而ChatGPT则较贵。 然而,AI依赖也带来隐忧,长期使用可能导致记忆衰退和“脑雾”现象。为此,推荐Neuriva解决方案,专注力提升30%,记忆留存率提升2.1倍,助力人类在AI时代保持脑力巅峰。 DeepSeek赢在技术普惠,ChatGPT胜于生态构建,人类的关键在于平衡AI与脑力健康,实现“双核驱动”突破极限!
1335 7
|
人工智能 搜索推荐 iOS开发
OpenAI推出适用于iPhone的ChatGPT,与Apple实现具有里程碑意义的AI整合
OpenAI推出适用于iPhone的ChatGPT,与Apple实现具有里程碑意义的AI整合

热门文章

最新文章