当前位置: 首页 > article >正文

深入理解并行与并发:C++/Python实例详解

万古教员有名言,自信人生二百年。
个人主页:oioihoii
喜欢内容的话欢迎关注、点赞、收藏!感谢支持,祝大家祉猷并茂,顺遂无虞

在这里插入图片描述

并行(Parallelism)和并发(Concurrency)是计算机科学中两个重要的概念,尤其在多线程和多进程编程中。虽然这两个术语经常被混用,但它们实际上有着不同的含义和应用场景。下面我们将详细探讨这两个概念的定义、区别、应用场景以及实例。

1. 定义

并发(Concurrency)

并发是指在同一时间段内处理多个任务的能力。并发并不一定意味着这些任务是同时执行的,而是指多个任务在逻辑上是同时进行的。并发可以通过时间分片(time-slicing)来实现,即在一个处理器上快速切换任务,使得用户感觉到多个任务在同时进行。

特点

  • 任务可以在同一时间段内交替执行。
  • 适用于 I/O 密集型任务(如网络请求、文件读写等)。
  • 主要关注任务的管理和调度。
并行(Parallelism)

并行是指在同一时刻同时执行多个任务。并行通常依赖于多核处理器或多台计算机,能够真正实现任务的同时执行。并行计算可以显著提高程序的执行效率,尤其是在 CPU 密集型任务中。

特点

  • 任务在物理上同时执行。
  • 适用于 CPU 密集型任务(如复杂计算、数据处理等)。
  • 主要关注任务的分解和执行。

2. 区别

特性并发(Concurrency)并行(Parallelism)
定义逻辑上同时处理多个任务物理上同时执行多个任务
任务执行方式任务交替执行(时间分片)任务同时执行(多核或多处理器)
适用场景I/O 密集型任务CPU 密集型任务
实现方式通过线程、协程、事件循环等通过多线程、多进程、分布式计算等
复杂性任务管理和调度较复杂任务分解和同步较复杂

3. 应用场景

并发的应用场景
  • Web 服务器:处理多个客户端请求,通常使用异步 I/O 或线程池来实现并发。
  • 用户界面:在 GUI 应用中,主线程负责界面响应,而后台线程处理耗时操作,保持界面流畅。
  • 网络爬虫:同时发起多个网络请求,快速抓取数据。
并行的应用场景
  • 科学计算:如天气模拟、分子动力学等,需要大量计算的任务可以分解为多个子任务并行执行。
  • 图像处理:对大图像进行滤镜处理时,可以将图像分成多个部分并行处理。
  • 大数据处理:使用 MapReduce 等框架对大规模数据集进行并行计算。

4. Python中的并发与并行

并发示例

假设我们有一个简单的程序,需要从多个 URL 下载数据。我们可以使用 Python 的 asyncio 库来实现并发下载:

import asyncio
import aiohttp

async def fetch(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()

async def main(urls):
    tasks = [fetch(url) for url in urls]
    return await asyncio.gather(*tasks)

urls = ['http://example.com', 'http://example.org', 'http://example.net']
asyncio.run(main(urls))

在这个例子中,fetch 函数是异步的,多个 URL 的下载是并发进行的,但并不一定是同时执行的。

并行示例

使用 Python 的 multiprocessing 模块来实现并行计算:

from multiprocessing import Pool

def square(n):
    return n * n

if __name__ == '__main__':
    numbers = [1, 2, 3, 4, 5]
    with Pool(processes=5) as pool:
        results = pool.map(square, numbers)
    print(results)

在这个例子中,square 函数会在多个进程中并行执行,真正实现了同时计算多个数字的平方。

举例说明

  • 并发:想象一下你在厨房里做饭,同时切菜、煮汤和烤面包。虽然你在同一时间段内做了这些事情,但实际上你可能在不同的时间段内完成了每一项任务。
  • 并行:如果你有多个厨师在厨房里,每个厨师负责不同的任务(一个切菜,一个煮汤,一个烤面包),那么这些任务就是并行执行的。

5. C++中的并发与并行

C++11引入了对多线程的支持,使得并发和并行编程变得更加容易。下面我们将通过示例代码来展示这两个概念。

并发示例

在这个示例中,我们将创建多个线程来模拟并发执行的任务。每个线程将打印一条消息,模拟一个耗时的操作。

#include <iostream>
#include <thread>
#include <vector>
#include <chrono>

void task(int id) {
    std::cout << "Task " << id << " is starting.\n";
    std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟耗时操作
    std::cout << "Task " << id << " is completed.\n";
}

int main() {
    std::vector<std::thread> threads;

    // 创建多个线程
    for (int i = 0; i < 5; ++i) {
        threads.emplace_back(task, i);
    }

    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }

    std::cout << "All tasks are completed.\n";
    return 0;
}
代码解析
  • 我们定义了一个task函数,模拟一个耗时的操作。
  • main函数中,我们创建了5个线程,每个线程执行task函数。
  • 使用std::this_thread::sleep_for来模拟每个任务的耗时。
  • 最后,我们使用join方法等待所有线程完成。
并行示例

在这个示例中,我们将使用C++的线程库来实现真正的并行计算。我们将计算一组数字的平方,并行处理这些计算。

#include <iostream>
#include <thread>
#include <vector>
#include <chrono>

void calculate_square(int number, int& result) {
    std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟耗时操作
    result = number * number;
    std::cout << "Square of " << number << " is " << result << ".\n";
}

int main() {
    std::vector<std::thread> threads;
    std::vector<int> results(5);
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    // 创建多个线程进行并行计算
    for (size_t i = 0; i < numbers.size(); ++i) {
        threads.emplace_back(calculate_square, numbers[i], std::ref(results[i]));
    }

    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }

    std::cout << "All calculations are completed.\n";
    return 0;
}
代码解析
  • 我们定义了一个calculate_square函数,计算给定数字的平方。
  • main函数中,我们创建了5个线程,每个线程处理一个数字的平方计算。
  • 使用std::ref将结果传递给线程,以便线程能够修改主线程中的结果。
  • 最后,我们等待所有线程完成。

6. 总结

  • 并发并行是处理多个任务的两种不同方式,前者强调任务的管理和调度,后者强调任务的同时执行。
  • 理解这两个概念对于设计高效的程序和系统至关重要,尤其是在现代多核处理器和分布式计算环境中。
  • 在实际应用中,选择并发还是并行取决于任务的性质(I/O 密集型还是 CPU 密集型)以及系统的架构。

进一步探讨交流以及更多惊喜关注公众号联系我!再次欢迎关注、点赞、收藏,系列内容可以点击专栏目录订阅,感谢支持,祝大家祉猷并茂,顺遂无虞
在这里插入图片描述

若将文章用作它处,请一定注明出处,商用请私信联系我!


http://www.kler.cn/a/538626.html

相关文章:

  • 【Ubuntu】安装和使用Ollama的报错处理集合
  • kubernetes 集群命令行工具 kubectl
  • Python 实现 gRPC 与 原始 RPC 的对比:理解 RPC 的基本功能
  • CANoe工具使用技巧 --- 如何使用 “on ethernetPacket “事件处理程序
  • 洛谷算法1-3 暴力枚举
  • android中关于CheckBox自定义选中图片选中无效问题
  • 迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-在产品中新增子系统
  • 链表专题-03
  • vmware虚拟机可以使用Windows的GPU吗
  • 【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter6-集合引用类型
  • git撤销上一次的提交
  • C# Winform怎么设计串口,客户端和相机控件界面显示
  • Win11下搭建Kafka环境
  • 2. UVM的基本概念和架构
  • 深度学习在医疗影像分析中的应用
  • [Meet DeepSeek] 如何顺畅使用DeepSeek?告别【服务器繁忙,请稍后再试。】
  • 前端【技术方案】浏览器兼容问题(含解决方案、CSS Hacks、条件注释、特性检测、Polyfill 等)
  • SQL写法:行行比较
  • 【R语言】数据分析
  • fatal:Authentication failed for “http....
  • 现在中国三大运营商各自使用的哪些band频段
  • 【Pycharm+Git+Gitlab】安装部署(粗糙版)
  • 电脑黑屏按什么键恢复?电脑黑屏的解决办法
  • [Redis] Redis分布式锁与常见面试题
  • Nginx中替换即将到期的SSL/TLS证书
  • 【开发电商系统的技术选型】