MST
星途 面试题库

面试题:Rust中实现简单并发计算曼德博集部分区域

请使用Rust的并发编程特性,实现计算曼德博集在复平面上一个指定矩形区域内各点的曼德博集归属状态(例如,判断每个点是否属于曼德博集)。要求使用线程池,并处理好线程间的数据共享和同步问题。简要阐述你使用的同步机制(如Mutex、Arc等)的作用和选择原因。
38.3万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

1. 实现代码

use std::sync::{Arc, Mutex};
use rayon::prelude::*;

// 判断一个复数是否属于曼德博集
fn is_in_mandelbrot(c: complex::Complex<f64>, max_iter: u32) -> bool {
    let mut z = complex::Complex::new(0.0, 0.0);
    for _ in 0..max_iter {
        if z.norm_sqr() > 4.0 {
            return false;
        }
        z = z * z + c;
    }
    true
}

fn mandelbrot_in_rectangle(
    x_min: f64,
    x_max: f64,
    y_min: f64,
    y_max: f64,
    width: u32,
    height: u32,
    max_iter: u32,
) -> Vec<Vec<bool>> {
    let mut result = vec![vec![false; width as usize]; height as usize];
    let result_arc = Arc::new(Mutex::new(result));

    (0..height).into_par_iter().for_each(|j| {
        let y = y_min + (y_max - y_min) * (j as f64 / (height - 1) as f64);
        let local_result = result_arc.lock().unwrap();
        for i in 0..width {
            let x = x_min + (x_max - x_min) * (i as f64 / (width - 1) as f64);
            let c = complex::Complex::new(x, y);
            local_result[j as usize][i as usize] = is_in_mandelbrot(c, max_iter);
        }
    });

    *result_arc.lock().unwrap()
}

2. 同步机制说明

  • Arc
    • 作用Arc(原子引用计数)用于在多个线程间共享数据。在上述代码中,result_arc是一个Arc<Mutex<Vec<Vec<bool>>>>,通过Arc使得多个线程可以持有对result数据结构的引用。
    • 选择原因:因为Vec<Vec<bool>>是一个较大的数据结构,将其在每个线程中进行拷贝是不现实的,Arc提供了一种在多个线程间高效共享数据的方式,并且它是线程安全的。
  • Mutex
    • 作用Mutex(互斥锁)用于保护共享数据,确保同一时间只有一个线程可以访问被保护的数据。在代码中,result_arc内部的Mutex保证了在对result进行读写操作时,不会出现数据竞争。
    • 选择原因:由于多个线程可能同时尝试修改result中的数据,Mutex提供了一种简单有效的同步机制,通过锁的方式来避免数据竞争,保证数据的一致性。

3. 关于rayon

在上述代码中,使用了rayon库的into_par_iter方法来并行处理任务。rayon库提供了一个线程池,能够自动管理线程的创建和销毁,并且它可以根据系统的CPU核心数来动态调整并行度,提高计算效率。

4. 注意事项

  • 上述代码中的complex类型假设是来自num-complex库,使用前需在Cargo.toml文件中添加依赖:
[dependencies]
num-complex = "0.4"
rayon = "1.5"
  • 实际应用中,可以根据具体需求调整max_iter、矩形区域的边界值以及图像的分辨率(widthheight)。