VLIW-指令宽度性能提高



由于处理器可以并行执行两倍多的操作,因此将VLIW中的指令量增加一倍会使处理器的性能提高一倍吗?

答案取决于计算类型。假设我们的机器上只有一个ALU。想象一下,我们有一个计算数组总和的代码:

for(int i = 0; i < len; i++)
{
sum += arr[i]
}

伪程序集如下所示:

; tick 0:
LD arr[i] -> %r0    ; load value from memory to register on ALU0
; tick 1:
ADD sum, %r0 -> sum ; increment sum value                on ALU0

循环体需要2个刻度。如果我们将ALU数加倍并展开循环体,我们将得到以下情况:

; tick 0:
LD arr[i] -> %r0    ; load value from memory to register on ALU0
LD arr[i+1] -> %r1  ; load value from memory to register on ALU1
; tick 1:
ADD sum, %r0 -> sum ; increment sum value                on ALU0
; tick 2:
ADD sum, %r1 -> sum ; increment sum value                on ALU0

现在我们可以看到,循环体需要3个刻度。可以进行并行加载,但计算本身不能并行,因为其结果取决于先前的循环迭代。因此,我们不会将ALU的数量增加一倍,从而使性能提高一倍。

现在我们来看另一个例子-两个向量的和:

for(int i = 0; i < len; i++)
{
c[i] = a[i] + b[i]
}

让我们看看伪汇编:

; tick 0:
LD a[i] -> %r0      ; load value a[i]     on ALU0
; tick 1:
LD b[i] -> %r1      ; load value b[i]     on ALU0
; tick 2:
ADD %r0, %r1 -> %r2 ; add values          on ALU0
; tick 3:
ST c[i] <- %r2      ; store value to c[i] on ALU0

我们用4个记号数尸体。如果我们将ALU的数量增加一倍会发生什么?在这种情况下,我们不依赖于以前的计算。因此,我们可以展开循环的主体,并获得以下代码:

; tick 0:
LD a[i] -> %r0      ; load value a[i]     on ALU0
LD b[i] -> %r1      ; load value b[i]     on ALU1
; tick 1:
LD a[i] -> %r0      ; load value a[i]     on ALU0
LD b[i] -> %r1      ; load value b[i]     on ALU1
; tick 2:
ADD %r0, %r1 -> %r2 ; add values          on ALU0
ADD %r0, %r1 -> %r2 ; add values          on ALU1
; tick 3:
ST c[i] <- %r2      ; store value to c[i] on ALU0
ST c[i] <- %r2      ; store value to c[i] on ALU1

我们仍然有4个节拍,但在这4个节拍中,我们计算了2次循环迭代。因此,我们可以说,ALU数量翻倍使我们的性能翻倍。

这些简单的例子只是说明了指令级并行性取决于特定的算法,而仅仅将ALU加倍可能会使性能加倍。

在更复杂的情况下,VLIW系统必须实现复杂的优化编译器,该编译器可以进行非VLIW的系统在硬件中实现的优化。在某些情况下,它的效果更好,在一些情况下,效果更差。

最新更新