星期日, 8月 11, 2019

Convolution Theorem and Overlap Save/Add Method



https://github.com/chenhsiu/remagic/blob/master/convolution.ipynb

The Overlap add/save method gives us an idea about how to use FFT to accelerate convolution. This method is generally much faster than typical pair-wise multiplication convolution by its definition. But how many performance gain we can get from this kind of FFT accelerated convolution? Let's do some experiments on the 2D convolution and see its result.


Convolution Theorem

First of all, let's try prove the convolution theorem with the python code.

From time domain

In [32]:
import numpy as np
from scipy.fftpack import fft, ifft, fftn, ifftn

x = [0, 0, 3, -1, 0]
h = [1, 1, 2, 1, 1]

X = fft(x)
H = fft(h)
r1 = np.real(ifft(X*H))

r2 = np.convolve(np.hstack((x[1:],x)), h, mode='valid')
print('%s == %s ? %s' % (r1, r2, 'Yes' if np.allclose(r1, r2) else 'No'))
[1. 2. 2. 2. 5.] == [1 2 2 2 5] ? Yes

From frequency domain

In [31]:
# frequency domain
X = np.array([1.+1.j, 2.+3.j, 1.+2.j, 3.+2.j])
H = np.array([2.+3.j, 1.+1.j, 3.+3.j, 4.+5.j])

Y = X * H
r1 = ifft(Y)
print('r1 = %s' % r1)

x = ifft(X)
h = ifft(H)
x = np.hstack((x[1:], x)) # by default is linear convolution, make it circular
r2 = np.convolve(x,h, mode='valid')
print('r2 = %s' % r2)

print('r1 == r2 ? %s' % ('Yes' if np.allclose(r1, r2) else 'No'))
r1 = [-0.75+10.5j   5.   -1.75j -1.25 -3.5j  -4.   -0.25j]
r2 = [-0.75+10.5j   5.   -1.75j -1.25 -3.5j  -4.   -0.25j]
r1 == r2 ? Yes

Time domain with different size signal

In [16]:
x = [7, 2, 3, -1, 0, -3, 5, 6]
h = [1, 2, -1]

X = fft(x)
H = fft(h, len(x))
r1 = ifft(X * H)
print('r1 = %s' % r1)
r2 = np.real(np.convolve(np.hstack((x[1:],x)),h,mode='valid'))
r2 = r2[len(r2) - len(x):]
print('r2 = %s' % r2)

print('r1 == r2 ? %s' % ('Yes' if np.allclose(r1, r2) else 'No'))
r1 = [ 1.40000000e+01+0.0000000e+00j  1.00000000e+01-2.2977602e-16j
 -1.11022302e-15+0.0000000e+00j  3.00000000e+00+2.2977602e-16j
 -5.00000000e+00+0.0000000e+00j -2.00000000e+00+6.5840240e-16j
 -1.00000000e+00+0.0000000e+00j  1.90000000e+01-6.5840240e-16j]
r2 = [14 10  0  3 -5 -2 -1 19]
r1 == r2 ? Yes

Fast Convolution with FFT

Now we see how the FFT can help us on fast convolution.
The convolve2d in scipy.signal uses pair-wised multiplication (see the source code ). Meanwhile, there is also a fftconvolve in scipy.signal which uses FFT to calculate convolution (see source code here). From its documentation:
This is generally much faster than convolve for large arrays (n > ~500), but can be slower when only a few output values are needed, and can only output float arrays (int or object array inputs will be cast to float).
For overlapadd2, we found a 2D overlap-add with FFT implementation on github. Below is its description:
Fast two-dimensional linear convolution via the overlap-add method. The overlap-add method is well-suited to convolving a very large array, Amat, with a much smaller filter array, Hmat by breaking the large convolution into many smaller L-sized sub-convolutions, and evaluating these using the FFT. The computational savings over the straightforward two-dimensional convolution via, say, scipy.signal.convolve2d, can be substantial for large Amat and/or Hmat.
The performance comparison result on my NB shows below:
methodconvolve2dfftconvolveoverlapadd2
speed3040 ms30.1 ms94.8 ms
We can see the FFT based convolution is generally much faster than typical convolution, from 30X to 100X acceleration. The result surprises me a bit because fftconvolve is still faster than overlapadd2. The overlapadd2 looks good and ideal, but the user still needs to tweak the size of L in order to get the best performance. Maybe overlapadd2 has the real benefits only when the input matrix is so big that can't be fit into memory and we have split into sub-convolutions.
One thing to note is, when we use FFT convolution on image processing, there will be a dark borders around the image, due to the zero-padding beyond its boundaries. The convolve2d function allows for other types of image boundaries, but is far slower.

Reference

There is an article doing 2D convolution benchmark with various convolution libraries:
In [75]:
# before you run, eval the cell containing overlapadd2 at the end

from scipy import misc
import scipy.signal as sp
import matplotlib.pyplot as plt

A = misc.ascent()
A = A.astype(float)
print(A.shape)
H = np.outer(sp.gaussian(64, 8), sp.gaussian(64, 8))

print('==> using convolve2d')
%time B1 = sp.convolve2d(A, H, mode='same')
print('==> using fftconvolve')
%time B2 = sp.fftconvolve(A, H, mode='same')
print('==> using overlapadd2')
%time B3 = overlapadd2(A, H)

fig, (ax_orig, ax_conv, ax_fft2conv, ax_ovadd2) = plt.subplots(1, 4, figsize = (12, 8))
ax_orig.imshow(A, cmap='gray')
ax_orig.set_title('Original')
ax_orig.set_axis_off()
ax_conv.imshow(B1, cmap='gray')
ax_conv.set_title('convolve2d')
ax_conv.set_axis_off()
ax_fft2conv.imshow(B2, cmap='gray')
ax_fft2conv.set_title('fftconvolve')
ax_fft2conv.set_axis_off()
ax_ovadd2.imshow(B3, cmap='gray')
ax_ovadd2.set_title('overlapadd2')
ax_ovadd2.set_axis_off()
fig.show()
(512, 512)
==> using convolve2d
CPU times: user 2.84 s, sys: 4.87 ms, total: 2.84 s
Wall time: 2.84 s
==> using fftconvolve
CPU times: user 28.4 ms, sys: 11 µs, total: 28.4 ms
Wall time: 28.8 ms
==> using overlapadd2
L = [288 288]
Nfft = [360 360]
CPU times: user 54 ms, sys: 1.89 ms, total: 55.9 ms
Wall time: 56.1 ms
/usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:32: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure.

星期日, 8月 26, 2018

SRE Book Ch 1&2


古人的名言說得好:『知易行難』。知道 Google SRE 這本書已經好一段時間了,還是最近才開始因為讀書會而好好的認真讀過。讀完前幾章的心路歷程是這樣的:
  1. 竊喜。過去的經驗畢竟還是有些用處的,看到有一樣的想法,不禁覺得英雄所見略同,還好這些日子沒白活。
  2. 扼腕。看著同樣的經歷活生生被寫在書本上,會覺得如果早點讀過,或許就不需用血淋淋的教訓去換取經驗。
  3. 期盼。個人的經驗總有限制,看到那些被寫出來的,沒經歷過的知識被整理得這麼完整,總想著若能真的實現該有多好,哪怕只是部分也好。
Google 也真夠意思,頭一兩章就擲地有聲,毫不囉唆,把 SRE 這件事整理歸納的很好。其中特別讓人感興趣的觀點是,Google 說 99.999% 跟 100% 根本沒差,SLA 從來就不是越高越好。甚至還引進 Error Budget 這個工具。
In general, for any software service or system, 100% is not the right reliability target because no user can tell the difference between a system being 100% available and 99.999% available. There are many other systems in the path between user and service (their laptop, their home WiFi, their ISP, the power grid…) and those systems collectively are far less than 99.999% available. Thus, the marginal difference between 99.999% and 100% gets lost in the noise of other unavailability, and the user receives no benefit from the enormous effort required to add that last 0.001% of availability.
人才濟濟如 Google,在 Dev 團隊與 SRE 團隊之間終究還是會有思維上的衝突,到底是該追求開發功能與速度,還是要維持高 availability 而盡量減少變動?Error Budget 是這麼看的:

假設我們的 SLA 是 99.95%,就表示每一季度可以接受 64.8 分鐘的 downtime。SLA 既然是 agreement,那就表示只要高於 99.95% 就是過關的,那麼這 64 分鐘就是可以拿來運用的預算:
  • 如果這一季度我們做得還不錯 (或是運氣特別好),沒有 downtime,那麼我們就有 64 分鐘的預算來上一些可能會有風險的新功能,萬一出事 SRE 團隊也不用太著急,因為情況不見得會失控
  • 如果這一季度 Dev 團隊的品質把關不夠嚴謹,已經有 40 分鐘的 downtime 了,那麼 Dev 團隊就乖一點,摸摸鼻子回頭想想怎麼改善
於是觀念一轉 ,突然間海闊天空了。原本吵得不可開交的爭執,變成大家來分餅,來分這塊 64 分鐘的 Error 大餅 (SRE 也可能想試一些較為 aggressive 的 infra change) 。

我們把場景換成 Dev 和 QA 之間 (如果有 QA 團隊的話),是不是 bug free 本身就是個假議題呢?如果沒有 P0 bug,是不是只要讓客戶維持在高度滿意的狀態即可,偶有 P1 或 P2 的 bug 只要傷害範圍不會太大即可?然後 QA 再也不會因為堅持完美而推遲 release,或是 Dev 再也不會為了嚐鮮而不顧產品品質?

同理如果是一個聰明的小孩,要做好 Mother Relationship Management 的話,就可以想想如何定義每個月的調皮預算 (Naughty Budget) — 把媽媽對於小孩乖巧度的期待控制在一個『有點乖又不會太乖』的程度,就可以適當的調皮搗蛋追求刺激,卻又不至於遭到被痛打的命運。

PS: 關於 SLA 這件事最好還是由業務端的人員去跟客戶好好商量 — 畢竟媽媽是無法開除小孩的,但客戶卻可以 XD


星期日, 10月 27, 2013

2013 澳洲遊

由於一直對南半球的天空有種浪漫的憧憬,加上有朋友住在澳洲,於是趁著國慶假期,規劃了一趟澳洲之旅,陸續拜訪了墨爾本以及雪梨這兩個城市。


講點旅途比較有趣的好了。

一開始抵達墨爾本,由於比跟朋友約定的時間早了不少,就想說先把 3G 網卡搞定,聯絡朋友也方便,就到附近的便利商店買預付卡。結果沒想到這個預付卡居然要『線上』開通。問題是我沒有網路,怎麼線上開通呢?到附近的 Hungry Jack 用免費的 wifi 看網頁,結果發現複雜到不行,乾脆打客服電話去開通。客服很熱情的想跟我聊天,說他也是亞洲人,在菲律賓,還問我看過袋鼠了沒有。我努力想把話題轉到開通這件事上,偏偏他又重複的推薦:You must plan to see kangaroo and koala, blah, blah。後來終於開通語音部分了,但數據連線還是有問題,只好跑一趟市區的電信門市才搞定。

所以下次到別的國家,還是直接去電信門市弄到好,不要隨便在超商買預付卡。

到盛產葡萄酒的澳洲,當然也要去酒莊晃晃。朋友帶我們去 Chandon,這家酒莊除了香檳很不錯之外,有名的就是被 LV 家族買下(大概是因為太常去買酒了,所以乾脆把整個酒莊買下來 XD)。


酒莊展售中心外就是一大片葡萄園,藍天綠地,簡直就像畫一樣。妙的是酒莊外的草坪上竟然停了一台直升機,有人走出來買酒,然後又達達達的搭直升機離開。果然有錢人的等級就是不一樣啊!

不管走在墨爾本或是雪梨,你都看的到不同國籍種族的人在街上行走,十足是個多元化的社會。相比之下,雪梨比較擁擠一點,路上行人也較匆忙,但各個港口景點比較豐富,尤其是搭配 MyMulti-3 的大眾運輸套票,連渡輪也可以無限次搭乘,從環形碼頭往來北雪梨的諸多碼頭,從海灣上欣賞雪梨的美,是很不一樣的體驗。


到了一個國家,最直接感受到的也是物價,原本以為德國物價已經很貴了,沒想到澳洲物價更貴。澳洲不只物價貴,凡事只要牽涉到人工的,一律貴到嚇人。所以這裡水電之類勞力的工作,薪資並不會比一般上班族差,而且愛做不做,每天準時上下班,假日更還要享受生活。連澳洲牛肉也沒有便宜到哪裡去,跟台灣買的到的澳洲牛肉價位差不多,吃起來當然也一樣。比較特別的是澳洲的羊肉特別好吃,完全沒有羊騷味,非常鮮美。


典型的澳洲人非常友善親切,走在路上自拍的時候常遇到主動說要幫我們拍照的人。澳洲人非常悠閒有禮,假日的時候在公園或是海灘邊,常常看到有人就直接躺在草地上曬太陽,或是拿一本書閱讀,也有拿一本筆記本寫著不知道什麼心得。澳洲人有著不錯的閱讀習慣,不管去到哪裡,很容易就可以看到人們閱讀,或是記著筆記,這在台灣可是很少見的。

澳洲另外有趣的,是他們的澳洲腔英語。基本上,他們的諸多用字也跟美式英語很不一樣。例如藥局通常是叫 pharmacy,但他們多用 chemist 這個字。我們常講 cool, great, 他們怎是喜歡講 beautiful (或是 lovely), 凡事總能來 beautiful 一下。喜歡講 mate, 沒事都來 mate 一下。


台灣最近流行『媽寶』一詞。實際上,台灣普遍有種奶娘文化,管東管西,把人民當小孩一樣管教,不管是捷運上的標語或是台籍的空姐,細心呵護到一種奇怪的感覺。這次搭乘澳航,飛機上的空媽空爸(年紀普遍大,但是親切有禮)才不管你那麼多,有問題再問,把大家都當成年人一般看待。各旅遊景點例如藍山或是企鵝島(飛利浦島),說實在的有些地方難免危險,但不見過高的護欄以及太多警告標語,所有人自重自律。『獨立自重』是身為一個成年人被社會要求的基本行為,只要在守法的範圍內,基本上尊重個別的行為舉止。


例如 Puffing Billy 蒸汽小火車,他最有名的就是行進過程中可以全程把手腳伸出車外,就這樣一路掛著行駛 40 分鐘以上,偶爾行經森林或草原,享受周邊新鮮的空氣以及大自然的美景。當然一路上列車與周邊都有一定的距離,基本上想搆都搆不到。這讓我想到阿里山的高山小火車,就沒有這樣的趣味。我相信因為大家都會這樣做,所以站方一定會維護行進間不會有異物傷害到乘客,大家有共識,都能自律自重自己負責任,也就減少了許多不必要的社會成本。

雖然澳洲物價高,人工貴,經濟這幾年也不好,但基本上他們拒絕加班,享受生活,堅持一份工作該有的最低待遇,也許因而物價指數會不斷上漲,但薪資也跟著上漲。整體算來,日子說不上富裕,多半過得去,但可以得到的生活品質卻是在台灣有錢都買不到。對比之下,台灣這幾年除了房價以外,基本上物價算平穩,拜大家努力追求 cost down 所賜,薪資也就十六年凍漲,加班文化盛行,人人辛勤工作。如果這麼除一除,高物價換來的生活品質換算成 CP 值卻可能還是比台灣要高的多。


不過這樣比較起來也不公平,台灣地小人綢,天然資源貧乏。澳洲則是得天獨厚,坐擁將近 80% 的中國土地面積,而人口竟只有兩千多萬。所以說這樣的生活品質很大部分是來自於豐厚的天然資源,只能說澳洲是個好命的富家子。不過這些我想逐漸也會因為移民政策而有所改變,澳洲法定時新是 16-18 澳幣左右,但各大城市的 working holiday 多的是每小時 8 澳幣的工作大家搶著做,仲介抽成,黑工也是時有所聞。外來人口政策很大程度會影響所謂的澳洲 style。儘管如此,這個富家子的家底實在太豐厚了,所以這塊土地上的人民真的是很受老天眷顧的一群人。

星期日, 8月 26, 2012

Code Rush - Mozilla 紀錄片

MozTW 軟體自由日《Code Rush》放映會
〈Code Rush〉是 David Winton 導演於 1998 年至 2000 年間拍攝的紀錄片,紀錄了矽谷的 Netscape 工程師們將瀏覽器原始碼釋出,成為 Mozilla 專案的經過;同時 Netscape 也正經歷被 AOL 併購的過程。本片描繪了 Netscape 的工程師們,犧牲日常生活與家庭,努力防止他們的公司倒閉的經歷。...

這部紀錄片詳實的記錄了程式設計師的生活, 對寫程式的熱情與執著, 矽谷的掏金夢, 投資銀行家的市儈與貪婪, 以及 2000 年當時尚未破滅的網路泡沫.

我在想, 其實不只是矽谷的 Netscape, 在台灣電子新貴的那個年代, 應該也有這麼一群群爆肝工程師, 犧牲日常生活與家庭, 用自己滿腔的熱血去鎔鑄擊殺競爭對手的神兵利器; 或是燃燒自己的生命去為落後的產品線爭取一線生機. 然而個人的熱情終究抵不過大環境的現實. 在面對 AOL 的併購, Netscape 員工只能落寞的安慰自己, "這畢竟比起被 Microsoft 併購要來的好得多".

這可能就像是, 平常熬夜加班, 企圖開發出更優異產品的晨星工程師, 在隔天看到被聯發科併購消息的時候, 心裡所感受到的一股失落.

然後 Netscape 的故事卻又讓我聯想到一篇文章 你絕對不應該做的事之一.

事無絕對, 也許就是有這麼多林林總總, 才有今日蓬勃發展的 Firefox.

lec-1 (2022-05-12) Accelerating deep learning computation & strategies

雖然用 DNN train/predict model 也好一陣子了,但這週才是第一次搞懂 cuDNN 是作什麼的 以前好奇過 tensorflow/pytorch 是怎麼做 convolution 的,FFT 不是比較好嗎? 下面的 reference 就給了很好的解釋: Wh...