我想知道 MATLAB 如何与矢量化操作一起工作?
Data1 = fread(fin1, 10e6, 'uint8');
Data2 = fread(fin2, 10e6, 'uint8');
DiffA = diff(Data1);
DiffB = diff(Data2);
MATLAB 是否使用一种 SIMD 并行性来执行此代码?它是使用矢量处理器(如GPU(还是仅使用系统内核(在多核系统中(?
MATLAB使用JIT来加速计算。我没有找到关于 JIT 的明确信息,只有一般建议。在我自己的用例中,我更喜欢将其视为Java JIT,因为优化技术非常匹配。 MATLAB 在提高性能方面做了 4 个主要步骤:
- 在R13(2002(中引入了JIT。
- 在 R2006b 中引入了没有临时存储的就地计算,请参阅文档第 7 页的详细信息 在R2007中
- 引入了多线程(在引擎中,而不是在并行工具箱中(,在R2008中被广泛采用
- 在R2016中引入了新引擎,JIT被广泛采用
有关更多详细信息,请参阅此博客文章,评论可能非常有用。我了解的主要事情是,在较新版本中,"全部清除"删除了会话代码中的预编译。 Yair Altman对JIT进行了修补,并写了一本关于MATLAB性能的完美书。有关 MATLAB JIT 的胆量和用法的一些详细信息,请点击此处。有关性能的介绍,我建议从官方手册开始
好的,首先首先考虑 C 而不是 MATLAB,因为 i( C 更接近机器和 ii(MATLAB 是用 C 语言编写的(至少,大多数语言执行引擎,几乎所有的数字代码都是用 C 编写的 - 目前桌面主要是基于 Java 的,但这在这里无关紧要(。
所以如果你在 C 中有一个循环,比如
for (i = 0; i < 1024; i++)
{
C[i] = A[i]*B[i];
}
这是要求计算机将A
和B
的元素一一添加到数组C
中。但是,某些处理器(矢量处理器,大多数现代 CPU 都是矢量处理器(可能能够使用 SIMD(单指令,多数据(指令一次执行其中的几个添加。所以你也许可以重写循环说
for (i = 0; i < 1024; i+=4)
{
C[i:i+3] = A[i:i+3]*B[i:i+3];
}
在这种情况下,将同时进行四次添加。这是矢量化 C 代码的一个简单示例,通过部分展开循环。
重要的是要注意,您不一定必须在 C 代码中显式执行此操作,因为您的 C 编译器非常聪明。它会注意到代码中可以矢量化的部分,并在编译之前为您重写这些部分。编译器非常擅长这一点,但它不能拾取所有内容,如果你了解矢量化在 CPU 中的工作原理,那么你可以通过以特定方式构建代码来给编译器提示,你可以明确地告诉编译器做特定的事情。
另请注意,这种矢量化虽然是一种简单的并行形式,但甚至可以在单核 CPU 上使用(只要它是矢量处理器,大多数现代 CPU 都是这样(。并行性发生在CPU的寄存器级别,通过使用相同的指令同时操作多个数据位。在多核 CPU 或 GPU 中的内核之间还存在其他形式的并行性。
现在回到 MATLAB - MATLAB 实现了多种形式的并行性,包括多线程、跨内核和集群上的显式并行性以及 GPU 并行性(其中一些需要附加产品,如并行计算工具箱(。但在其核心,MATLAB 实现了一组高度优化、高度矢量化的 C 例程,用于数值处理和线性代数。
与C不同,MATLAB不是一种编译语言 - 它是使用JIT编译器进行解释的。但它仍在查看您的代码并尝试找到可以使用的优化,以便快速执行它。如果您以特定方式编写代码,则可以帮助 MATLAB 选择如何以最佳方式执行它。
例如,代码
a = rand(3,4);
b = rand(4,2);
c = zeros(size(a,1),size(b,2));
for i = 1:size(a,1)
for j = 1:size(b,2)
element = 0;
for k = 1:size(a,2)
element = element + a(i,k).*b(k,j);
end
c(i,j) = element;
end
end
执行相同的操作
a = rand(3,4);
b = rand(4,2);
d = a*b;
但在后一种情况下,MATLAB 知道它可以调用其超级优化库之一进行矩阵乘法,而不是逐个乘法和累加元素。这是矢量化 MATLAB 代码的一个简单示例。