Main Content

使用并行 for 循环 (parfor) 的算法加速

生成的代码中的并行 for 循环 (parfor)

为了尽可能加速执行,您可以从包含并行 for 循环(parfor 循环)的 MATLAB® 代码生成 MEX 函数或 C/C++ 代码。

parfor 循环(与标准 MATLAB for 循环类似)对一个范围内的值执行一系列语句(循环体)。然而,与 for 循环不同,parfor 循环的迭代可以在目标硬件的多个核上并行运行。

并行运行迭代可显著提高生成的代码的执行速度。有关详细信息,请参阅parfor 循环如何提高执行速度

注意

并行执行只发生在生成的 MEX 函数或 C/C++ 代码中;而不会不发生在原始 MATLAB 代码中。要加速您的 MATLAB 代码执行速度,请从 parfor 循环中生成 MEX 函数。然后,从您的代码中调用 MEX 函数。有关详细信息,请参阅加速 MATLAB 算法的工作流

要在您的 MATLAB 代码中使用 parfor,您需要 Parallel Computing Toolbox™ 许可证。

MATLAB Coder™ 软件使用 Open Multiprocessing (OpenMP) 应用程序接口来支持共享内存、多核代码生成。如果需要分布式并行机制,请使用 Parallel Computing Toolbox 产品。默认情况下,MATLAB Coder 会使用它所能找到的所有可用核。如果指定要使用的线程数,MATLAB Coder 会使用针对这些线程的最大核数量,即使有其他可用核也是如此。有关详细信息,请参阅 parfor

由于循环体可以在多个线程上并行执行,因此它必须遵守某些限制。如果 MATLAB Coder 软件检测到不符合 parfor 设定的循环,则会产生错误。有关详细信息,请参阅 parfor 限制

parfor 循环如何提高执行速度

parfor 循环可提供高于其同类 for 循环的执行速度,因为多个线程可以对同一循环以并发方式执行计算。

parfor 循环体的每次执行称为一次迭代。这些线程以任意顺序执行迭代计算,且彼此独立。由于每次迭代都是独立的,因此它们不必同步。如果线程数等于循环迭代次数,则每个线程将执行一次循环迭代。如果迭代次数超过线程数,则某些线程将执行多次循环迭代。

例如,当包含 100 次迭代的循环在 20 个线程上运行时,每个线程将同时执行五次循环迭代。如果循环因包含大量迭代或单个迭代过长而需要很长时间才能运行完毕,您可以使用多个线程来显著减少运行时间。不过,在此示例中,速度提升可能达不到 20 倍,因为存在并行化开销(如线程创建和删除)。

何时使用 parfor 循环

在下列情况下,请使用 parfor

  • 多次简单计算迭代。parfor 会将这些循环迭代分为若干组,以使每个线程执行一组迭代。

  • 一次循环迭代需要很长时间才能执行完毕。parfor 可在不同线程上同时执行迭代。虽然这种同时执行不会减少单个迭代所花费的时间,但它可以大大减少整个循环所花费的总时间。

何时不使用 parfor 循环

在下列情况下,请不要使用 parfor

  • 循环的某次迭代依赖于其他迭代。并行运行迭代可能导致错误的结果。

    为了避免在循环的某次迭代依赖于其他迭代时使用 parforMATLAB Coder 指定了变量的刚性分类。有关详细信息,请参阅 Classification of Variables in parfor-Loops。如果 MATLAB Coder 检测到循环不符合 parfor 设定,将不会生成代码并且会产生错误。

    规则要求循环迭代必须是独立的,但归约是一个例外。归约变量会将依赖于所有迭代的值累加在一起,但与迭代顺序无关。有关详细信息,请参阅Reduction Variables

  • 只有几次执行一些简单计算的迭代。

    注意

    对于少量循环迭代,由于存在并行化开销,可能并不能提升执行速度。此类开销包括线程创建、线程之间的数据同步以及线程删除所花费的时间。

parfor 循环语法

  • 对于 parfor 循环,请使用以下语法:

    parfor i = InitVal:EndVal 
    parfor (i = InitVal:EndVal) 
    

  • 要指定最大线程数,请使用以下语法:

    parfor (i = InitVal:EndVal,NumThreads) 
    

有关详细信息,请参阅 parfor

parfor 限制

  • parfor 循环不支持以下语法:

    parfor (i=initVal:step:endVal) 
    parfor i=initVal:step:endVal

  • 必须使用支持 Open Multiprocessing (OpenMP) 应用程序接口的编译器。请参阅支持的编译器。如果使用不支持 OpenMP 的编译器,则 MATLAB Coder 会将 parfor 循环视为 for 循环。在生成的 MEX 函数或 C/C++ 代码中,循环迭代在单个线程上运行。

  • OpenMP 应用程序接口与 JIT MEX 编译不兼容。请参阅 JIT Compilation Does Not Support OpenMP

  • 循环索引的类型必须可由目标硬件上的整数类型表示。在生成的代码中使用不需要多字类型的类型。

  • 用于独立代码生成的 parfor 需要工具链方法来编译可执行文件或库。

  • 不要在 parfor 循环体中使用以下构造:

    •  嵌套 parfor 循环

    •  break 和 return 语句

    •  全局变量

    •  MATLAB 类使用归约

    •  char 变量使用归约

    •  使用外部 C 代码的归约

    •  外部函数调用

    •  内联函数

    •  展开循环

    •  varargin/varargout