2019年1月7日 星期一

OpenMP : 一個成熟穩定、使用 CPU 多核心的 library

一般單執行緒 (mono-thread) 的 code,多核心處理器是沒有辦法提升處理效能的,但多執行緒(multi-thread)的 code,可以透過多核心的平行計算,來達到加速目的。那要怎麼簡單使用CPU的多核心計算資源呢?  OpenMP 就是一個好答案。

OpenMP 在 1997 年就開始了,一直維護改版至今。算是很穩定與老牌的函式庫了。
https://www.openmp.org/
https://zh.wikipedia.org/wiki/OpenMP

使用方法: (編輯 test.c)

#include     // 引入library
#include
#include

int main(int argc, char* argv[]) 
 { 
   #pragma omp parallel    //這一行很重要
   printf("Hello, world.\n"); 
   return 1; 
 }


編譯方法: (編譯 test.c)

gcc -o test -fopenmp test.c


直接執行編譯出來的執行檔即可


解釋

語法
#pragma omp [clause[[,] clause] ...]  

其中,directive共11個:
  • atomic 記憶體位置將會原子更新(Specifies that a memory location that will be updated atomically.)
  • barrier 執行緒在此等待,直到所有的執行緒都執行到此barrier。用來同步所有執行緒。
  • critical 其後的程式碼塊為臨界區,任意時刻只能被一個執行緒執行。
  • flush 所有執行緒對所有共用物件具有相同的記憶體視圖(view of memory)
  • for 用在for迴圈之前,把for迴圈並列化由多個執行緒執行。迴圈變數只能是整型
  • master 指定由主執行緒來執行接下來的程式。
  • ordered 指定在接下來的程式碼塊中,被並列化的 for迴圈將依序執行(sequential loop)
  • parallel 代表接下來的程式碼塊將被多個執行緒並列各執行一遍。
  • sections 將接下來的程式碼塊包含將被並列執行的section塊。
  • single 之後的程式將只會在一個執行緒(未必是主執行緒)中被執行,不會被並列執行。
  • threadprivate 指定一個變數是執行緒局部儲存(thread local storage)

共計13個clause:
  • copyin 讓threadprivate的變數的值和主執行緒的值相同。
  • copyprivate 不同執行緒中的變數在所有執行緒中共用。
  • default Specifies the behavior of unscoped variables in a parallel region.
  • firstprivate 對於執行緒局部儲存的變數,其初值是進入並列區之前的值。
  • if 判斷條件,可用來決定是否要並列化。
  • lastprivate 在一個迴圈並列執行結束後,指定變數的值為迴圈體在順序最後一次執行時取得的值,或者#pragma sections在中,按文字順序最後一個section中執行取得的值。
  • nowait 忽略barrier的同步等待。
  • num_threads 設定執行緒數量的數量。預設值為目前電腦硬體支援的最大並行數。一般就是CPU的內核數目。超執行緒被作業系統視為獨立的CPU內核。
  • ordered 使用於 for,可以在將迴圈並列化的時候,將程式中有標記 directive ordered 的部份依序執行。
  • private 指定變數為執行緒局部儲存。
  • reduction Specifies that one or more variables that are private to each thread are the subject of a reduction operation at the end of the parallel region.
  • schedule 設定for迴圈的並列化方法;有 dynamic、guided、runtime、static 四種方法。
    • schedule(static, chunk_size) 把chunk_size數目的迴圈體的執行,靜態依序指定給各執行緒。
    • schedule(dynamic, chunk_size) 把迴圈體的執行按照chunk_size(預設值為1)分為若干組(即chunk),每個等待的執行緒獲得目前一組去執行,執行完後重新等待分配新的組。
    • schedule(guided, chunk_size) 把迴圈體的執行分組,分配給等待執行的執行緒。最初的組中的迴圈體執行數目較大,然後逐漸按指數方式下降到chunk_size。
    • schedule(runtime) 迴圈的並列化方式不在編譯時靜態確定,而是推遲到程式執行時動態地根據環境變數OMP_SCHEDULE 來決定要使用的方法。
  • shared 指定變數為所有執行緒共用。


細節可參考 Wiki

2018年12月23日 星期日

route 53 域名 連到 ec2

EC2 建立就不多說,
1. 選擇基本設定,建立虛擬機。把 IP 從 dashboard 複製下來。
2. 記得 key pair 要把 .pem 檔保存下來。一般來說用 puTTYgen 轉成 .ppk 供 putty 使用。如果有設密碼保護,會在你連線 ec2 時問帳密,若用 Ubuntu,帳號名稱會是 ubuntu,密碼會是 所設的密碼保護。若沒在 key 設密碼保護,就會用 .ppk 直接登入。

去到 route 53 想設定的域名裡面,選擇 create record set

把想要的主機名稱填入右側 NAME
把 IP 填入 Value 即可

申請 AWS SSL 憑證

申請憑證方法很簡單,只要十分鐘以內就完成。

首先,要擁有自己的 domain name,我已經在 AWS route 53 上申請好了。

再來,進到 AWS 的 certificate manager : https://aws.amazon.com/tw/certificate-manager/


選取佈建憑證。(我們沒有要建立自己的私有憑證機制)


申請公有憑證。

把自己的網址打進來,我是使用 *. 作 domain 開頭。

因我們有 route 53 可以自己設定 DNS,所以選擇 DNS 驗證。確認檢閱後,則會出現:

將給出來的 CNAME 名稱,與值都複製下來。

進到 route 53,點入你要設定的域名裡,點選 create recorder set:


選擇 type 為 CNAME,將剛剛 CNAME 的名稱填入右方 NAME,值填入右方 VALUE。

點選 create 以後,要等個三五分鐘,等待 DNS 資料在網路傳播開來。再回去 certificate manager 看,就會成為 "已發行" 的狀態。 至此成功。




2018年11月15日 星期四

在 Pytorch Tensor 裡把 RGB 轉為 BGR


非在 影像層次,如果已經在 tensor 層次,要把 RGB 轉為 BGR 也不困難:

# 產生一個亂數 RGB
> t = torch.Tensor(np.arange(12).reshape(4, 3))
# 轉換的排列 RGB --> BGR
> permute = [2, 1, 0] > t[:, permute] tensor([[ 2., 1., 0.], [ 5., 4., 3.], [ 8., 7., 6.], [ 11., 10., 9.]])

就可以轉換成功

2018年11月12日 星期一

GPU 測量好物


Techpowerup

https://www.techpowerup.com/download/techpowerup-gpu-z/

2018年10月31日 星期三

PM專欄 1: 軟體週期與系統週期 ?!

System Development Life Cycle (SDLC) vs Software Development Life Cycle

SDLC vs SDLC?!

這是甚麼東西? 軟體開發生命週期(Software Development Life Cycle) 跟系統開發生命週期(System Development Life Cycle) 是不同的涵蓋面。

軟體開發流程包含了軟體工程所熟悉的: 需求分析、軟體設計、軟體實作、測試、部署、後續維護等等。但是系統開發生命週期就包含更多應該考量的因素,例如: 人的管理、流程管理、硬體相關設施與架構、人員訓練、組織佈達等等層面。

有此一說,當然也有人混用這些定義,不過這個也給我們比較宏觀另一面向的思考。

2018年10月11日 星期四

Pytorch 實作 word embedding : 運用 nn.Embedding()


Pytorch 產生 word embedding : 運用 nn.Embedding()

用法


torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False, _weight=None)


num_embeddings (int) : embeddings 字典裡面有多少個詞
embedding_dim (int) : 產生的 embedding vector 要有多少維度?  --> 這個要自己決定

其他細節參數看這裡


範例


import torch
import torch.nn as nn 
from torch.autograd import Variable 

# embedding 字典
word_dict = {'hello': 0, 'paul': 1, 'chao': 2} #三個詞,三個相對 tensors 數值

embeds = nn.Embedding(3, 10) #三個詞(tensors數值),設十維

#從 dictionary 產生 tensor 數值
paul_idx = torch.LongTensor([word_dict['paul']]) 
print(paul_idx) 

#產生變數
paul_idx = Variable(paul_idx) 
print(paul_idx) 

#進行 embedding
paul_embed = embeds(paul_idx) 
print(paul_embed)



結果


tensor([2])
tensor([2])
tensor([[ 1.3302,  0.4645,  0.5615, -0.0327,  1.5131, -1.9684, -0.8720, -0.5227, 1.2371,  0.6098]], grad_fn=)

最後便產生了一個十維的 word embedding 可供運用