You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Pylab的森林火势演化图像程序运行缓慢及崩溃问题排查求助

Troubleshooting Slow Performance & Crashes in Your Forest Fire Simulation

Hey there! Let's break down why your forest fire simulation is running sluggishly and crashing, plus fix it up to run smoothly. The core issues boil down to inefficient loops, non-vectorized operations, and suboptimal visualization updates—here's how to tackle each:

1. Python Nested Loops Are Killing Performance

Your code relies heavily on nested for loops (e.g., Initialise, Affiche, Evolution, Voisins) to iterate over every pixel individually. Python is slow at looping, and when you stack multiple loops (like checking 8 layers of neighbors in Evolution), the time complexity skyrockets. This is the biggest culprit for slowdowns.

Fix: Use NumPy Vectorization

NumPy operations are implemented in C, so they’re way faster than Python loops. Replace your per-pixel loops with vectorized logic:

Example: Optimized Initialise

import numpy as np

def Initialise(n,p,t,c,r):
    # Generate tree matrix in one go with numpy random
    R = np.random.choice([0, 1], size=(n,p), p=[1-t, t])
    
    # Protected trees area (70-100, 60-100)
    protected_area = R[70:100, 60:100]
    mask = np.random.random(protected_area.shape) <= c
    protected_area[mask & (protected_area == 1)] = 10
    
    # Clear area with random trees (10-40,10-40)
    clear_area = R[10:40,10:40]
    clear_area[:] = 0
    tree_mask = np.random.random(clear_area.shape) <= r
    clear_area[tree_mask] = 1
    
    # Geologic site (20-40,80-90)
    R[20:40,80:90] = 4
    
    return R

Example: Optimized Affiche

def Affiche(M):
    n,p = M.shape
    img = np.zeros((n,p,3), dtype=np.uint8)
    
    # Vectorized condition assignments
    img[M == 0] = sol
    img[M == 1] = arbre
    img[M == 10] = arbreprotege
    img[M == 4] = ressourceprotegee
    
    return img

2. Inefficient Neighbor Checking (Voisins Function)

Your Voisins function uses multiple loops to check each neighbor layer one by one. This is redundant and slow, especially when called for every pixel in Evolution.

Fix: Use Sliding Window/Convolution for Batch Neighbor Checks

Instead of checking each pixel individually, use NumPy slicing or scipy.ndimage to detect burning areas in bulk:

from scipy.ndimage import binary_dilation

def get_burning_mask(M):
    # Create a boolean mask of burning pixels (rouge, orange, jaune)
    is_burning = (M == rouge).all(axis=2) | (M == orange).all(axis=2) | (M == jaune).all(axis=2)
    return is_burning

def Evolution(M):
    R = M.copy()
    n,p = M.shape[:2]
    
    # Get burning mask and expand it for each neighbor distance (1-8)
    burning_mask = get_burning_mask(M)
    for k in range(1,9):
        # Expand burning area by k pixels
        expanded = binary_dilation(burning_mask, structure=np.ones((2*k+1, 2*k+1)))
        # Find trees that are in expanded area and haven't caught fire yet
        trees_to_burn = (expanded) & ((R == arbre).all(axis=2) | (R == arbreprotege).all(axis=2))
        # Apply ignition probability (decreasing with k)
        proba = 0.6 - (k-1)*0.05
        ignition_mask = np.random.random(trees_to_burn.shape) < proba
        R[trees_to_burn & ignition_mask] = rouge
    
    # Update burning stages (rouge → orange → jaune → noir)
    R[(R == rouge).all(axis=2)] = orange
    R[(R == orange).all(axis=2)] = jaune
    R[(R == jaune).all(axis=2)] = noir
    
    return R

3. Slow Fire Status Check (Feu Function)

Your Feu function loops through every pixel to check for burning trees. Replace it with a vectorized check:

def Feu(M):
    is_burning = (M == rouge).all(axis=2) | (M == orange).all(axis=2) | (M == jaune).all(axis=2)
    return np.any(is_burning)

4. Visualization Updates Causing Crashes

Your ForetBrule function calls pl.show() and image.changed() (which isn’t a valid Matplotlib method) repeatedly. This overloads the GUI thread, leading to crashes.

Fix: Streamline Visualization

def ForetBrule(M):
    plt.ion()
    fig, ax = plt.subplots()
    image = ax.imshow(M)
    plt.show(block=False)
    
    while plt.fignum_exists(fig.number) and Feu(M):
        M = Evolution(M)
        image.set_data(M)
        fig.canvas.draw_idle()  # Efficiently update the plot
        plt.pause(0.1)
    
    plt.ioff()

5. Miscellaneous Fixes

  • Remove the unused global Em line in Evolution—it’s unnecessary and could cause unexpected behavior.
  • Use numpy.random instead of the standard random module for faster, vectorized random number generation.
  • Ensure all color tuples are compatible with NumPy array operations (they are in your code, but double-check for type mismatches).

After applying these changes, your simulation should run orders of magnitude faster without crashing—vectorized operations eliminate most of the Python loop overhead, and the visualization updates are optimized to avoid GUI overload.

内容的提问来源于stack exchange,提问作者Bastien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 18:07:46