Python协程详解:从基础到实战

news2025/4/25 6:42:25

协程是Python中实现并发编程的重要方式之一,它比线程更轻量级,能够高效处理I/O密集型任务。本文将全面介绍协程的概念、原理、实现方式以及与线程、进程的对比,包含完整的效率对比代码和详细说明,帮助Python开发者深入理解并掌握协程技术。

1. 协程基础概念

1.1 什么是协程

协程(Coroutine)是Python中另外一种实现多任务的方式,它是一种比线程更小的执行单元,占用更少的资源。协程之所以被称为执行单元,是因为它自带CPU上下文。这意味着只要在合适的时机,我们可以把一个协程切换到另一个协程,只要在这个过程中保存或恢复CPU上下文,程序就可以继续运行。

通俗地说:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行(注意不是通过调用函数的方式做到的),并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定。

1.2 为什么需要协程

在传统多线程编程中,我们知道:

  • 进程是资源分配的最小单位

  • 线程是CPU调度的最小单位

虽然多线程已经提高了CPU利用率,但创建和管理线程/进程需要消耗系统资源。随着对效率的追求不断提高,基于单线程实现并发成为一个新的课题,即只用一个主线程(很明显可利用的CPU只有一个)情况下实现并发。这样可以节省创建线程/进程所消耗的时间。

1.3 并发的本质

并发的本质可以概括为:切换+保存状态

CPU正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操作系统强制控制):

  1. 该任务发生了阻塞(如I/O操作)

  2. 该任务计算的时间过长(时间片用完)

其中第二种情况并不能提升效率,只是为了让CPU能够"雨露均沾",实现看起来所有任务都被"同时"执行的效果。如果多个任务都是纯计算的,这种切换反而会降低效率。

2. 协程与线程的差异

在实现多任务时,线程切换从系统层面远不止保存和恢复CPU上下文这么简单。操作系统为了程序运行的高效性,每个线程都有自己缓存Cache等数据,操作系统还会帮你做这些数据的恢复操作。所以线程的切换非常耗性能。

相比之下,协程的切换只是单纯地操作CPU的上下文,所以一秒钟切换个上百万次系统都抗得住。具体差异如下:

特性线程协程
调度者操作系统用户程序
切换代价高(涉及内核态切换)低(用户态切换)
内存占用较大(MB级)极小(KB级)
并发数量有限(千级)极高(百万级)
数据同步需要锁机制无需加锁

3. Python协程的特点

  1. 必须在单线程里实现并发:协程的本质是单线程下的并发

  2. 修改共享数据不需加锁:因为是单线程,不存在竞争条件

  3. 用户程序自己保存多个控制流的上下文栈

  4. 自动I/O切换:一个协程遇到I/O操作自动切换到其它协程(需要gevent等模块支持)

4. Python协程的实现方式

4.1 yield模拟协程

Python中的生成器(generator)和yield关键字可以初步模拟协程的行为:

def consumer():
    while True:
        x = yield  # 接收send发送的值
        print(f"处理数据: {x}")

def producer():
    c = consumer()
    c.__next__()  # 启动生成器
    for i in range(5):
        print(f"生产数据: {i}")
        c.send(i)  # 发送数据给consumer

producer()

这段代码展示了生产者-消费者模型的基本协程实现。生产者通过send()方法将数据发送给消费者,消费者通过yield接收并处理数据。

4.2 Greenlet模块

Greenlet是一个更专业的协程实现,它提供了明确的切换方法:

from greenlet import greenlet
import time

def task1():
    print("执行任务1")
    gr2.switch()  # 切换到任务2
    print("任务1继续执行")
    gr2.switch()

def task2():
    print("执行任务2")
    gr1.switch()  # 切换回任务1
    print("任务2继续执行")

gr1 = greenlet(task1)
gr2 = greenlet(task2)
gr1.switch()  # 启动任务1

Greenlet的优点是切换明确,缺点是需要手动切换,无法自动识别I/O阻塞。

4.3 Gevent模块

Gevent是基于Greenlet的更高级协程库,它能够自动处理I/O阻塞:

import gevent
from gevent import monkey
monkey.patch_all()  # 打补丁,替换标准库中的阻塞式I/O

def fetch(url):
    print(f"获取 {url}")
    gevent.sleep(2)  # 模拟I/O操作
    print(f"{url} 返回数据")

def async_fetch():
    urls = ['url1', 'url2', 'url3']
    jobs = [gevent.spawn(fetch, url) for url in urls]
    gevent.joinall(jobs)

async_fetch()

Gevent的关键点:

  1. monkey.patch_all():替换Python标准库中的阻塞式I/O为Gevent的非阻塞版本

  2. gevent.spawn():创建协程任务

  3. gevent.joinall():等待所有协程完成

5. 协程效率对比测试

5.1 顺序执行 vs 协程执行

下面我们通过一个完整的例子来对比顺序执行和协程执行的效率差异:

from gevent import monkey
import gevent
import time
import requests

# 打补丁
monkey.patch_all()

# 测试URL
url = "https://www.baidu.com"

# 顺序执行
def sequential_fetch():
    start = time.time()
    for i in range(5):
        print(f"顺序请求 {i} 开始")
        response = requests.get(url)
        print(f"顺序请求 {i} 完成,状态码: {response.status_code}")
    print(f"顺序执行总耗时: {time.time() - start:.2f}秒")

# 协程执行
def coroutine_fetch():
    start = time.time()
    def fetch(i):
        print(f"协程请求 {i} 开始")
        response = requests.get(url)
        print(f"协程请求 {i} 完成,状态码: {response.status_code}")
    
    jobs = [gevent.spawn(fetch, i) for i in range(5)]
    gevent.joinall(jobs)
    print(f"协程执行总耗时: {time.time() - start:.2f}秒")

# 执行测试
print("=== 顺序执行测试 ===")
sequential_fetch()

print("\n=== 协程执行测试 ===")
coroutine_fetch()

执行结果分析

  • 顺序执行:每个请求依次执行,总耗时≈各请求耗时之和

  • 协程执行:所有请求并发执行,总耗时≈最慢的单个请求耗时

5.2 线程 vs 协程效率对比

下面我们对比线程和协程在处理I/O密集型任务时的效率:

import threading
import time
import requests
from gevent import monkey
import gevent

monkey.patch_all()
url = "https://www.baidu.com"
n = 10  # 并发数量

# 线程方式
def thread_fetch():
    start = time.time()
    
    def fetch(i):
        response = requests.get(url)
        print(f"线程 {i} 完成")
    
    threads = []
    for i in range(n):
        t = threading.Thread(target=fetch, args=(i,))
        t.start()
        threads.append(t)
    
    for t in threads:
        t.join()
    
    print(f"线程方式总耗时: {time.time() - start:.2f}秒")

# 协程方式
def gevent_fetch():
    start = time.time()
    
    def fetch(i):
        response = requests.get(url)
        print(f"协程 {i} 完成")
    
    jobs = [gevent.spawn(fetch, i) for i in range(n)]
    gevent.joinall(jobs)
    print(f"协程方式总耗时: {time.time() - start:.2f}秒")

# 执行测试
print("=== 线程方式测试 ===")
thread_fetch()

print("\n=== 协程方式测试 ===")
gevent_fetch()

执行结果分析

  • 线程方式:创建线程有一定开销,线程切换需要内核参与

  • 协程方式:协程创建和切换开销极小,完全在用户空间完成

5.3 不同并发量下的效率对比

我们测试不同并发量下协程的执行效率:

import time
from gevent import monkey
import gevent
import requests

monkey.patch_all()

def test_concurrency(concurrency):
    print(f"\n=== 并发数: {concurrency} ===")
    start = time.time()
    
    def task(i):
        requests.get("https://www.baidu.com")
        print(f"任务 {i} 完成", end=" | ")
    
    jobs = [gevent.spawn(task, i) for i in range(concurrency)]
    gevent.joinall(jobs)
    
    elapsed = time.time() - start
    print(f"\n并发数 {concurrency} 总耗时: {elapsed:.2f}秒")
    return elapsed

# 测试不同并发量
concurrency_levels = [10, 50, 100, 200, 500]
results = {}
for level in concurrency_levels:
    results[level] = test_concurrency(level)

# 打印结果对比
print("\n=== 结果汇总 ===")
for level, time_cost in results.items():
    print(f"并发数 {level}: {time_cost:.2f}秒")

预期结果

  • 小并发量时总耗时接近单个请求耗时

  • 随着并发量增加,总耗时增长缓慢

  • 协程可以轻松支持上千并发

6. 协程的实际应用

6.1 网络爬虫

协程特别适合网络爬虫这种I/O密集型应用:

import gevent
from gevent import monkey
monkey.patch_all()
import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup

base_url = "https://www.example.com"
visited = set()

def crawler(url):
    if url in visited:
        return
    visited.add(url)
    
    try:
        print(f"抓取: {url}")
        response = requests.get(url)
        soup = BeautifulSoup(response.text, 'html.parser')
        
        # 处理页面内容...
        print(f"从 {url} 找到 {len(soup.find_all('a'))} 个链接")
        
        # 发现新链接
        links = [urljoin(base_url, a['href']) for a in soup.find_all('a', href=True)]
        
        # 创建协程抓取新链接
        jobs = [gevent.spawn(crawler, link) for link in links if link.startswith(base_url)]
        gevent.joinall(jobs)
    except Exception as e:
        print(f"抓取 {url} 出错: {e}")

# 开始抓取
crawler(base_url)

6.2 Web服务器

使用协程可以轻松实现高并发的Web服务器:

from gevent.pywsgi import WSGIServer
from gevent import monkey
monkey.patch_all()

def application(env, start_response):
    path = env['PATH_INFO']
    
    if path == '/':
        start_response('200 OK', [('Content-Type', 'text/html')])
        return [b"<h1>Welcome</h1><p>Hello from Gevent server!</p>"]
    
    elif path == '/api/data':
        # 模拟数据库查询
        gevent.sleep(1)
        start_response('200 OK', [('Content-Type', 'application/json')])
        return [b'{"data": [1, 2, 3]}']
    
    else:
        start_response('404 Not Found', [('Content-Type', 'text/html')])
        return [b"<h1>404 Not Found</h1>"]

if __name__ == '__main__':
    print("Server running on http://localhost:8000")
    server = WSGIServer(('0.0.0.0', 8000), application)
    server.serve_forever()

6.3 数据库操作

协程化的数据库操作可以显著提高并发性能:

import gevent
from gevent import monkey
monkey.patch_all()
import pymysql
from DBUtils.PooledDB import PooledDB

# 创建数据库连接池
db_pool = PooledDB(
    creator=pymysql,
    host='localhost',
    user='root',
    password='123456',
    db='test',
    maxconnections=20
)

def query_user(user_id):
    conn = db_pool.connection()
    try:
        with conn.cursor() as cursor:
            sql = "SELECT * FROM users WHERE id = %s"
            cursor.execute(sql, (user_id,))
            result = cursor.fetchone()
            print(f"查询到用户 {user_id}: {result}")
            return result
    finally:
        conn.close()

# 并发查询多个用户
user_ids = [1, 2, 3, 4, 5]
jobs = [gevent.spawn(query_user, uid) for uid in user_ids]
gevent.joinall(jobs)

7. 协程与多线程、多进程的对比

7.1 完整对比表格

特性进程线程协程
创建开销大(10+MB)中(1MB左右)极小(几KB)
切换开销高(微秒级)中(微秒级)低(纳秒级)
内存占用独立内存空间共享进程内存共享线程内存
数据共享IPC机制全局变量全局变量
并发数量数十个数百个数十万个
CPU利用多核多核(受GIL限制)单核
适用场景CPU密集型I/O+少量CPUI/O密集型
编程复杂度中(需同步)
稳定性高(隔离性好)中(一个线程崩溃影响整个进程)中(一个协程出错可能影响其他协程)

7.2 性能对比测试

下面我们通过一个完整的测试来对比进程、线程和协程的性能差异:

import time
import multiprocessing
import threading
from gevent import monkey
import gevent

monkey.patch_all()

# 测试任务:模拟I/O密集型操作
def task(n):
    gevent.sleep(1)  # 模拟I/O操作
    return n * n

# 进程方式
def process_way():
    start = time.time()
    pool = multiprocessing.Pool(processes=10)
    results = pool.map(task, range(10))
    pool.close()
    pool.join()
    print(f"进程方式 结果: {results} 耗时: {time.time() - start:.2f}秒")

# 线程方式
def thread_way():
    start = time.time()
    threads = []
    results = []
    
    def worker(n):
        results.append(task(n))
    
    for i in range(10):
        t = threading.Thread(target=worker, args=(i,))
        t.start()
        threads.append(t)
    
    for t in threads:
        t.join()
    
    print(f"线程方式 结果: {results} 耗时: {time.time() - start:.2f}秒")

# 协程方式
def coroutine_way():
    start = time.time()
    jobs = [gevent.spawn(task, i) for i in range(10)]
    gevent.joinall(jobs)
    results = [job.value for job in jobs]
    print(f"协程方式 结果: {results} 耗时: {time.time() - start:.2f}秒")

# 执行测试
print("=== 进程方式测试 ===")
process_way()

print("\n=== 线程方式测试 ===")
thread_way()

print("\n=== 协程方式测试 ===")
coroutine_way()

预期结果

  • 进程方式:耗时≈1秒,但创建进程开销大

  • 线程方式:耗时≈1秒,受GIL影响

  • 协程方式:耗时≈1秒,但资源占用最少

8. 协程最佳实践

8.1 避免CPU密集型任务

协程不适合纯CPU计算任务,下面是一个反面例子:

import time
from gevent import monkey
import gevent

monkey.patch_all()

# CPU密集型任务
def cpu_intensive(n):
    result = 0
    for i in range(n):
        result += i * i
    return result

# 测试协程执行CPU密集型任务
def test_coroutine_cpu():
    start = time.time()
    jobs = [gevent.spawn(cpu_intensive, 1000000) for _ in range(10)]
    gevent.joinall(jobs)
    print(f"协程执行CPU密集型任务耗时: {time.time() - start:.2f}秒")

# 测试顺序执行
def test_sequential_cpu():
    start = time.time()
    results = [cpu_intensive(1000000) for _ in range(10)]
    print(f"顺序执行CPU密集型任务耗时: {time.time() - start:.2f}秒")

print("=== CPU密集型任务测试 ===")
test_coroutine_cpu()
test_sequential_cpu()

结论:对于CPU密集型任务,协程不会带来性能提升,反而可能因为切换开销而降低性能。

8.2 合理控制并发量

虽然协程很轻量,但也需要合理控制并发量:

from gevent import monkey
import gevent
import requests
import time

monkey.patch_all()

def fetch(url, semaphore):
    with semaphore:  # 控制并发量
        print(f"开始请求 {url}")
        response = requests.get(url)
        print(f"完成请求 {url} 状态码: {response.status_code}")

def controlled_concurrency(url, concurrency=10, total=100):
    start = time.time()
    semaphore = gevent.pool.Semaphore(concurrency)  # 并发信号量
    jobs = [gevent.spawn(fetch, url, semaphore) for _ in range(total)]
    gevent.joinall(jobs)
    print(f"总请求数: {total} 并发数: {concurrency} 总耗时: {time.time() - start:.2f}秒")

# 测试不同并发控制
url = "https://www.baidu.com"
controlled_concurrency(url, concurrency=10, total=100)
controlled_concurrency(url, concurrency=20, total=100)
controlled_concurrency(url, concurrency=50, total=100)

8.3 异常处理

正确处理协程中的异常:

import gevent
from gevent import monkey
monkey.patch_all()

def successful_task():
    return "成功完成任务"

def failing_task():
    raise Exception("任务执行失败")

def handle_exceptions():
    jobs = [
        gevent.spawn(successful_task),
        gevent.spawn(failing_task),
        gevent.spawn(successful_task)
    ]
    
    gevent.joinall(jobs)
    
    for job in jobs:
        if job.successful():
            print(f"任务结果: {job.value}")
        else:
            print(f"任务失败: {job.exception}")

print("=== 异常处理测试 ===")
handle_exceptions()

9. 常见问题解答

Q: 协程能利用多核CPU吗?
A: 单个协程不能,因为它在单线程中运行。但可以通过多进程+协程的方式利用多核,例如每个进程运行一个事件循环。

Q: 协程会取代线程吗?
A: 不会完全取代。协程适合I/O密集型场景,线程适合需要利用多核或与C扩展交互的场景。最佳实践是根据需求选择合适的并发模型。

Q: Gevent的monkey patch安全吗?
A: 在大多数情况下是安全的,但应注意:

  1. 尽早调用monkey.patch_all()

  2. 避免与其他修改标准库的库同时使用

  3. 生产环境中先充分测试

Q: 如何调试协程程序?
A: 调试协程程序可以使用:

  1. 打印日志

  2. gevent.getcurrent()获取当前协程

  3. 使用支持协程的调试器如PyCharm专业版

10. 总结

协程是Python中强大的并发编程工具,特别适合I/O密集型应用。通过本文的完整介绍和代码示例,我们了解了:

  1. 协程的基本概念和原理

  2. Python中实现协程的三种方式:yield、greenlet、gevent

  3. 完整的效率对比测试代码和结果分析

  4. 协程在实际项目中的应用场景

  5. 协程与线程、进程的详细对比

  6. 协程编程的最佳实践和常见问题

掌握协程技术可以让你的Python程序在处理高并发时更加高效和优雅。希望本文能帮助你全面理解Python协程,并在实际项目中灵活应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2342204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

空闲列表:回收和再利用

空闲列表&#xff1a;回收和再利用 手动与自动内存管理 手动管理&#xff1a;程序员需要明确地分配和释放内存。自动管理&#xff1a;例如使用垃圾收集器(GC)&#xff0c;它能够自动检测并回收未使用的对象&#xff0c;不需要程序员干预。 对于某些数据结构如B树&#xff0c;…

计算机组成与体系结构:直接内存映射(Direct Memory Mapping)

目录 CPU地址怎么找到真实的数据&#xff1f; 内存映射的基本单位和结构 1. Pages&#xff08;页&#xff09;——虚拟地址空间的基本单位 2. Frames&#xff08;页框&#xff09;——物理内存空间的基本单位 3. Blocks&#xff08;块&#xff09;——主存和缓存之间的数据…

STM32提高篇: 蓝牙通讯

STM32提高篇: 蓝牙通讯 一.蓝牙通讯介绍1.蓝牙技术类型 二.蓝牙协议栈1.蓝牙芯片架构2.BLE低功耗蓝牙协议栈框架 三.ESP32-C3中的蓝牙功能1.广播2.扫描3.通讯 四.发送和接收 一.蓝牙通讯介绍 蓝牙&#xff0c;是一种利用低功率无线电&#xff0c;支持设备短距离通信的无线电技…

SpringMVC处理请求映射路径和接收参数

目录 springmvc处理请求映射路径 案例&#xff1a;访问 OrderController类的pirntUser方法报错&#xff1a;java.lang.IllegalStateException&#xff1a;映射不明确 核心错误信息 springmvc接收参数 一 &#xff0c;常见的字符串和数字类型的参数接收方式 1.1 请求路径的…

【程序员 NLP 入门】词嵌入 - 上下文中的窗口大小是什么意思? (★小白必会版★)

&#x1f31f; 嗨&#xff0c;你好&#xff0c;我是 青松 &#xff01; &#x1f308; 希望用我的经验&#xff0c;让“程序猿”的AI学习之路走的更容易些&#xff0c;若我的经验能为你前行的道路增添一丝轻松&#xff0c;我将倍感荣幸&#xff01;共勉~ 【程序员 NLP 入门】词…

从物理到预测:数据驱动的深度学习的结构化探索及AI推理

在当今科学探索的时代&#xff0c;理解的前沿不再仅仅存在于我们书写的方程式中&#xff0c;也存在于我们收集的数据和构建的模型中。在物理学和机器学习的交汇处&#xff0c;一个快速发展的领域正在兴起&#xff0c;它不仅观察宇宙&#xff0c;更是在学习宇宙。 AI推理 我们…

大模型AI的“双刃剑“:数据安全与可靠性挑战与破局之道

在数字经济蓬勃发展的浪潮中&#xff0c;数据要素已然成为驱动经济社会创新发展的核心引擎。从智能制造到智慧城市&#xff0c;从电子商务到金融科技&#xff0c;数据要素的深度融合与广泛应用&#xff0c;正以前所未有的力量重塑着产业格局与经济形态。 然而&#xff0c;随着…

操作系统概述与安装

主流操作系统概述 信创平台概述 虚拟机软件介绍与安装 windows server 安装 centos7 安装 银河麒麟V10 安装 一&#xff1a;主流服务器操作系统 &#xff08;1&#xff09;Windows Server 发展历程&#xff1a; 1993年推出第一代 WindowsNT&#xff08;企业级内核&am…

开发了一个b站视频音频提取器

B站资源提取器-说明书 一、功能说明 本程序可自动解密并提取B站客户端缓存的视频资源&#xff0c;支持以下功能&#xff1a; - 自动识别视频缓存目录 - 将加密的.m4s音频文件转换为标准MP3格式 - 将加密的.m4s视频文件转换为标准MP4格式&#xff08;合并音视频流&#xff09;…

基于javaweb的SpringBoot校园服务平台系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

PHYBench:首个大规模物理场景下的复杂推理能力评估基准

2025-04-23, 由北京大学物理学院和人工智能研究所等机构共同创建的 PHYBench 数据集&#xff0c;这是一个专门用于评估大型语言模型在物理场景下的复杂推理能力的高质量基准。该数据集包含 500 道精心策划的物理问题&#xff0c;覆盖力学、电磁学、热力学、光学、现代物理和高级…

Red:1靶场环境部署及其渗透测试笔记(Vulnhub )

环境介绍&#xff1a; 靶机下载&#xff1a; https://download.vulnhub.com/red/Red.ova 本次实验的环境需要用到VirtualBox&#xff08;桥接网卡&#xff09;&#xff0c;VMware&#xff08;桥接网卡&#xff09;两台虚拟机&#xff08;网段都在192.168.152.0/24&#xff0…

深入详解人工智能数学基础——概率论中的KL散度在变分自编码器中的应用

🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C++, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C++、C#等开发语言,熟悉Java常用开发技术,能熟练应用常用数据库SQL server,Oracle,mysql,postgresql等进行开发应用…

测试模版x

本篇技术博文摘要 &#x1f31f; 引言 &#x1f4d8; 在这个变幻莫测、快速发展的技术时代&#xff0c;与时俱进是每个IT工程师的必修课。我是盛透侧视攻城狮&#xff0c;一名什么都会一丢丢的网络安全工程师&#xff0c;也是众多技术社区的活跃成员以及多家大厂官方认可人员&a…

Openharmony 和 HarmonyOS 区别?

文章目录 OpenHarmony 与 HarmonyOS 的区别&#xff1a;开源生态与商业发行版的定位差异一、定义与定位二、技术架构对比1. OpenHarmony2. HarmonyOS 三、应用场景差异四、开发主体与生态支持五、关键区别总结六、如何选择&#xff1f;未来展望 OpenHarmony 与 HarmonyOS 的区别…

uniapp 仿小红书轮播图效果

通过对小红书的轮播图分析&#xff0c;可得出以下总结&#xff1a; 1.单张图片时容器根据图片像素定高 2.多图时轮播图容器高度以首图为锚点 3.比首图长则固高左右留白 4.比首图短则固宽上下留白 代码如下&#xff1a; <template><view> <!--轮播--><s…

R/G-B/G色温坐标系下对横纵坐标取对数的优势

有些白平衡色温坐标系会分别对横纵坐标取对数运算。 这样做有什么优势呢? 我们知道对数函数对0-1之间的因变量值具有扩展作用。即自变量x变化比较小时,经过对数函数作用后可以把因变量扩展到较大范围内,即x变化较小时,y变化较大,增加了识别数据的识别性。 由于Raw数据中的…

AI赋能安全调度系统:智能升级与功能跃迁

安全调度系统通过AI技术的深度整合&#xff0c;实现了从传统监控到智能决策的质变升级。这种智能化转型不仅提升了系统的响应速度和处理精度&#xff0c;更重塑了整个安全管理的运行范式。以下是AI技术为安全调度系统带来的核心功能强化&#xff1a; 智能风险识别与预警能力跃…

数据结构与算法(十二):图的应用-最小生成树-Prim/Kruskal

相关文献&#xff1a; 数据结构与算法(一)&#xff1a;基础理论 数据结构与算法(二)&#xff1a;线性表的实现 数据结构与算法(三)&#xff1a;线性表算法设计练习 数据结构与算法(四)&#xff1a;斐波那契数列 数据结构与算法(五)&#xff1a;LRU 数据结构与算法(六)&#xff…

项目——高并发内存池

目录 项目介绍 做的是什么 要求 内存池介绍 池化技术 内存池 解决的问题 设计定长内存池 高并发内存池整体框架设计 ThreadCache ThreadCache整体设计 哈希桶映射对齐规则 ThreadCache TLS无锁访问 CentralCache CentralCache整体设计 CentralCache结构设计 C…