CodeHighlight

2013年10月5日 星期六

[DS]Link list 實作 by C

這次是Link List的練習,新增node的部分是用stack的概念,
本身是單向的list,刪除是針對特定Data做刪除,
Reverse的部分稍微卡了一下,那三個指標的平移不熟悉的話,回傳的指標是指向神秘的未知空間呀!


#include<stdio.h>
#include<stdlib.h>

typedef struct node{
        int data;
        struct node *link;
}NODE;


NODE* addNode(NODE* head, int addData){
        NODE *newNode;
        newNode = (NODE*)malloc(sizeof(NODE));
        newNode->data = addData;
        newNode->link = head;
        head = newNode;
        return head;
}

NODE* delNode(NODE* head, int delData){
        NODE *preNode = NULL;
        NODE *firstNode = head;
        NODE *tmpNode;
        if(head == NULL){
                printf("EMPTY LIST\n");
                return;
        }
        while(head != NULL){    //Find Each Node
                if(head->data == delData){
                        tmpNode = head;
                        if(preNode != NULL){
                                preNode->link = head->link;
                        }
                        else{//List Head
                                firstNode = head->link;
                        }
                        free(tmpNode);
                }
                else{
                        preNode = head;
                        head = head->link;
                }
        }
        return firstNode;
}

NODE* reverseList(NODE *head){
        NODE *p,*t,*r;
        p = NULL;
        t = head;
        r = head->link;
        while(t != NULL){
                r = t->link;
                t->link = p;
                p = t;
                t = r;
        }
        return p;
}

void showAllList(NODE* head){
        if(head == NULL){
                printf("EMPTY LIST\n");
                return;
        }
        while(head != NULL){
                printf("%d->", head->data);
                head = head->link;
        }
        printf("\n");
}

int main(){
        NODE *head;
        head = addNode(head, 1);
        head = addNode(head, 2);
        head = addNode(head, 3);
        head = addNode(head, 4);
        head = addNode(head, 5);
        head = addNode(head, 6);
        head = addNode(head, 7);
        head = addNode(head, 8);
        head = addNode(head, 1);
        head = addNode(head, 2);
        head = addNode(head, 3);
        head = addNode(head, 4);
        head = addNode(head, 5);
        head = addNode(head, 6);
        head = addNode(head, 7);
        head = addNode(head, 8);

        showAllList(head);
        head = reverseList(head);
        showAllList(head);
        head = delNode(head, 2);
        showAllList(head);
        return 0;
}

2013年9月28日 星期六

[DS]Queue 實作 by C

這次像上篇一樣,不過改練習Queue的實作,
基本概念就是先進先出,是只做了enQueue、deQueue、listQueue三個

是說很久沒有寫了,在enQueue的地方還有點懷疑這樣寫到底正不正確XD


#include<stdio.h>
#include<stdlib.h>

typedef struct node{
        int data;
        struct node *next;
}NODE;

NODE* inQueue(NODE *top, int input){
        NODE *newNode;
        NODE *headPtr = top;
        newNode = (NODE*)malloc(sizeof(NODE));
        newNode->data = input;
        newNode->next = NULL;
        if(top == NULL){
                return newNode;
        }
        while(top->next != NULL){       //move to last
                top = top->next;
        }
        top->next = newNode;
        return headPtr;
}

NODE* deQueue(NODE *top){
        NODE *tmpNode = top;
        if(top == NULL){return top;}
        top = top->next;
        free(tmpNode);
        return top;
}

void listQueue(NODE* top){
        if(top == NULL){
                printf("EMPTY QUEUE\n");
                return;
        }
        while(top != NULL){
                printf("%d ", top->data);
                top = top->next;
        }
        printf("\n");
}

int main(){
        NODE *node;
        node = inQueue(node, 1);
        listQueue(node);
        node = inQueue(node, 2);
        listQueue(node);
        node = inQueue(node, 3);
        listQueue(node);
        node = deQueue(node);
        listQueue(node);
        node = deQueue(node);
        listQueue(node);
        node = deQueue(node);
        listQueue(node);
        node = deQueue(node);
        listQueue(node);
        node = inQueue(node, 1);
        node = inQueue(node, 2);
        node = inQueue(node, 3);
        node = inQueue(node, 4);
        node = inQueue(node, 5);
        listQueue(node);
        node = deQueue(node);
        node = deQueue(node);
        node = deQueue(node);
        listQueue(node);
        return 0;
}

2013年9月15日 星期日

[DS]Stack 實作 by C

最近看論文陷入一個瓶頸,感覺還是寫code實際,
突然想到很久沒有寫看看基本的資料結構了,所以決定回頭用C寫個stack,
順便複習一下指標的用法。
#include<stdio.h>
#include<stdlib.h>

typedef struct node{
        char data1;
        struct node *Link;
}NODE;

NODE* initSteak(NODE *top){
        top = NULL;
        return top;
}

NODE* pushSteak(NODE* top, char data){
        NODE *newBlock;
        newBlock = (NODE*)malloc(sizeof(NODE));
        newBlock->data1 = data;
        newBlock->Link = top;
        top = newBlock;
        return top;
}

NODE* popSteak(NODE *top){
        NODE *tmpBlock = top;
        top = top->Link;
        free(tmpBlock);
        return top;
}

void listSteak(NODE *top){
        while(!isEmpty(top)){
                printf("%c ", top->data1);
                top = top->Link;
        }
        printf("\n");
}

int isEmpty(NODE* top){
        return (top == NULL);
}

int main(){
        NODE *node;
        node = initSteak(node);

        node = pushSteak(node, 'a');
        node = pushSteak(node, 'b');
        listSteak(node);
        node = popSteak(node);
        listSteak(node);
        node = pushSteak(node, 'c');
        node = pushSteak(node, 'd');
        node = pushSteak(node, 'e');
        listSteak(node);
        node = popSteak(node);
        node = popSteak(node);
        node = popSteak(node);
        listSteak(node);
}

2013年8月31日 星期六

[PHP]用PHP讀docx相關函式

由於最近需要處理大量檔案內的資料搜尋,據傳docx檔案是由大量XML所組成,
所以我想應該會有可以解析的函式可用,果然在stackoverflow找到有人分享相關的函式:

<?php
     function read_file_docx($filename){  
         $striped_content = '';  
         $content = '';  
         if(!$filename || !file_exists($filename)) return false;  
         $zip = zip_open($filename);  
         if (!$zip || is_numeric($zip)) return false;  
         while ($zip_entry = zip_read($zip)) {  
             if (zip_entry_open($zip, $zip_entry) == FALSE) continue;  
             if (zip_entry_name($zip_entry) != "word/document.xml") continue;  
              $content .= zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));  
              zip_entry_close($zip_entry);  
          }// end while  
          zip_close($zip);  
          //echo $content;  
          //echo "&lt;hr&gt;";  
          //file_put_contents('1.xml', $content);  
          $content = str_replace('&lt;/w:r&gt;&lt;/w:p&gt;&lt;/w:tc&gt;&lt;w:tc&gt;', " ", $content);  
          $content = str_replace('&lt;/w:r&gt;&lt;/w:p&gt;', "\r\n", $content);  
          $striped_content = strip_tags($content);  
          return $striped_content;  
      }  
      $filename = "customers.docx";  
      $content = read_file_docx($filename);  
      if($content !== false) {  
          echo nl2br($content);  
      }  
      else {  
          echo 'Couldn\'t the file. Please check that file.';  
      }
?>

目前測試的感覺還不錯,格式部分也幾乎都會保留,如果做純粹座內文搜尋的話,是相當足夠的!


[C++] Thread Function相關測試

因為研究測試資料莫名的大,在生成資料的過程中,常常會有需要長時間等待的狀況,
這時就會想到當初課堂說的平行化處理,所以想說用thread來榨乾CPU的效能呀~

很幸運的是,在C++ 11之後,已經把thread列入標準凾式庫內了,
雖然早期的Compiler沒有支援,不過如果用IDE有乖乖升級的話,
應該之後的版本都會把這東西補進去
所以可以把那精美的pthread先放在一旁(pthread你好難懂呀~)

小弟在這邊個環境是在ubuntu上面,gcc version 4.4.3,
(真的比較習慣用vim寫code,直接上server跑資料也比較方便)

在使用上,編譯需要加上相關參數:
g++ source.cpp -std=c++0x -lpthread -Os -o ./target

  1. -std=c++0x:指定編譯的C++版本
  2. -lpthread:引入thread的lib,是說也看到有-pthread的,目前測過兩個都可以


在程式碼內,需要引入「thread」的函式:#include <thread>
這樣就可以呼叫thread相關函式來奴役充分利用CPU的資源了

在使用上,根據不同情境,使用的狀況會有所不同:

  1. 在main呼叫一般function

    這應該是最容易理解的,根據cplusplus.com的範例,他的程式碼長這個樣子:

    // thread example
    #include <iostream>       // std::cout
    #include <thread>         // std::thread
     
    void foo() 
    {
      // do stuff...
    }
    
    void bar(int x)
    {
      // do stuff...
    }
    
    int main() 
    {
      std::thread first (foo);     // 開新thread:「first」執行「foo」函式
      std::thread second (bar,0);  // 開新thread:「second」執行「bar」函式,傳入參數0
    
      std::cout << "main, foo and bar now execute concurrently...\n";
    
      // synchronize threads:
      first.join();                // 等「first」thread執行結束
      second.join();               // 等「second」thread執行結束
    
      std::cout << "foo and bar completed.\n";
    
      return 0;
    }
    因為C++ 11 thread已經將這個功能物件化,所以使用上就和使用一般物件一樣,
    先生成一個物件,然後將要分工執行的function和參數傳進去,這時候main function就只要等待執行結束在收割結果就好啦!

  2. 在class內呼叫同個class內的member function

    不過有時候,我們會需要在class裡面,針對特定的工作進行加速,像是某些需要大量重複計算又互不干擾的函式,這時候就會對單一個member function做thread加速,那這時得使用會變成:

    #include <iostream>
    #include <thread>
    
    using namespace std;
    
    ClassA::ClassA(){
    
    // do stuff...
    } void ClassA::memberFunA(int a){
    // do stuff...
    } void ClassA::memberFunB(){
    std::thread first (&ClassA::memberFunA, this, 0);
    first.join(); 
    // do stuff...
    }
    以上面為例,memberFunB需要呼叫同一個class的memberFunA,因此需要引入member function的完整reference,並且第一個參數要代入是自己這個class,讓thread可以正確找到要引入的資料為何。
  3. 在main呼叫特定物件的member function

    另一個情況是:在main function中需要將某些物件放到thread裡面做平行化運算:

    #include <iostream>
    #include <thread>
    using namespace std;
    
    int main( int argc, char** argv )
    {
          ClassA object1;
    
    std::thread first (&ClassA::memberFunA, &object1, 0);
    first.join(); 
    }
    在這邊的想法和2.類似:引入的function需要指定class和member function的reference,加上由於是用物件形式呼叫member function,因此需要在指定該物件的reference,才可以存取該物件內的member function
不過要注意的是,在引入物件進去thread平行化執行時,是將整個函式和變數複製一份到thread使用,因此如果有需要保留修改變數的狀況的話(EX: 引入一個陣列,裡面存修改後的狀況,讓多個thread個別修改一段),則需要加上「std::ref()」來處理。

以上大概就是C++裡面thread的基本使用,其實還有很多像是針對執行中thread的操作啦,thread間的溝通之類的東西,不過目前小弟還用不到那麼進階的功能,所以在這邊就先不提啦,之後有機會的話會再補上去。

2013年8月2日 星期五

[linux]常用ls參數

指令名稱:ls

用途:查詢該資料夾檔案內容

常見用法:

ls -c 依檔名順序排序 (由a到z)

ls -r 依檔名反向排序 (由z到a)

ls --sort=XXX 依照檔名以你指定的方式排序,XXX可以為:
  • # extension -- 以副檔名為排序依據( 也就是 ls -X )
  • # none ( 也就是 ls -U )
  • # size -- 以檔案大小為排序依據 ( 也就是 ls -S )
  • # time -- 以檔案存取時間為排序依據 ( 也就是 ls -t )
  • # version -- 以版本為排序依據 ( 也就是 ls -v)


參考資料:村仔仔的學習手札

2013年7月17日 星期三

[課程]雲端計算重點整理(期中)

這份是之前修課時留下的共筆,這邊稍微做個整理:


第一章
HPC: High Performance Computing
以效能為主要考量,主要用途作為科學計算之用

HTC: High Throughput Computing
以可以處理的task數量為考量,作為商用平台之使用。

Centralized computing:
集中式計算,所有的資源皆由單一個os作分配處理,如Data centers 與 supercomputers
本身重視效能的提升

Parallel computing:
平行式計算,與Centralized computing不同,所有task會被分配置不同的hardware上面平行化計算,Parallel computer 本身需要相對應的 parallel programs
本身重視彈性

Distributed computing:
分散式計算,其分散式系統本身有多個獨立的PC,每個都有獨立的硬體支援,利用
message passing來做訊息交換

Cloud computing:
雲端計算,本身是基於Parallel computing或Distributed computing,本身可建製在實體或虛擬系統上

BLP:
bit‐level parallelism,在bit計算上本身作平行化處理

ILP:
instruction‐level parallelism,在指令規格作平行化處理

DLP:
data‐level parallelism,在data處理層級上作平行化,本身有SIMD特性(signle instruction, multiple data)

TLP/JLP:
針對task/job作平行化,在遙遠的未來也許有機會實現。

Graphics processing units (GPUs)
當初設計目的以計算圖像為主,現已可協助科學計算,本身由多個功能較弱之cpu組成,利用同步計算以達到大量計算能量之目的。

IaaS為提供基礎設施,透過主機託管或環境提供作為外包服務的機制,如IBM,Amazon.com

PaaS為提供現有平台,供廠商或資訊人員於此開發服務的機制,常見如Facebook、Google的API

SaaS為直接提供現有可供終端使用者使用之服務,像是Youtube、Facebook、Plurk、Skype等Web應用程式。

Amdahl’s Law:
Speedup = S = T/[αT+(1-α)T/n]  =>α為不能平行化的比例,αT為不能平行處理的時間,(1-α)T/n 為n個process平行處理後的時間

Efficiency = E = S/n => n為process數量

Gustafson’s Law:
Speedup = S = [αW+(1-α)nW]/W
Efficiency = E = S/n
fixed workload => 用Amdahl’s Law
scaled problem => 用Gustafson’s Law

DVFS(dynamic voltage-frequency scaling):是利用判斷目前所需計算能量的狀況,來判斷是否要提升或降低其系統提供之voltage frequency,藉此達到省電的目的。
------------------------------------------------------------------------------------------------------------------
multi-core: 多個一樣的核心組合而成,ex intel core 2 series(CPUs)
many-core:多個不同或相同的核心組合而成,ex intel core i7(CPUs+GPUs+...)
第二章

SSI: Single-System Image,希望Cluster可以執行起來像一個系統一樣。(如同將多個電腦完全整合成單一系統,可像一般PC一樣使用。)

cluster架構中,各個node間分享資源的方法:
share-nothing(最常用,效率最低)
share-disk
share-memory(實作難度高,效率較好)
cluster中,node功能分成:
compute nodes-->用於負責數值計算
Service nodes-->負責I/O控制、file access、系統監控。

GPU cluster計算能量上較CPU cluster高,用來做大量數值運算為主。

RAID: 磁碟陣列,是目前分散式儲存的典型之一,基本概念是多顆硬碟串連,儲存時將資料分別儲存在多顆硬碟中,如此當其中一顆硬碟故障時,資料仍可由另外四顆救回。
目前最常見的類型是RAID5

System availability: MTTF/(MTTF(failure)+MTTR(repair))
用來計算系統的存活率

checkpoint:
用於增進系統或程式的availability,利於debugging, process migration, load balancing,使用時會增加時間和空間的負擔。可設置在不同level,如kernel level, user space(利用checkpointing library)及application(利用插入checkpointing function)

check用在parallel programs: 由於會有race condition,因此目前實做上仍有困難

Space sharing:
希望能以tiling(貼磁磚)法進行排程(請配合ppt圖解服用),但因無法真正預測job的長度與時間,因此在實作上有難度。

Time sharing:
透過time sharing, 將job切成等分小塊,讓CPU在各個小job間快速切換執行,達到類似tiling的效果
當有cluster job(remote job,也就是非本機任務)和local job並行時,排程更加複雜,因此local job可以設定有更高的priority以簡化此問題
Group time-sharing scheduling:
cluster是以非同步方式進行,不是由同一個clock驅動
當一個平行的job的process是active時,所有的processes也都是active,對於homogeneous clusters較有效率



Job Management System(JMS): 本身為scheduling的機制,分成三大部分:
-->User server:使用者送出的job會進入queue中做等待,管控queue與queue內部的job
-->Job scheduler:根據job的類型、資源需求、資源可取得性...來做scheduling
-->Resource management: 監控資源狀況,以利做為scheduling的依據,資源可能橫跨所有cluster node



JMS Administration:
管理configuration、log等需集中放置之檔案
能夠清除或殺掉job、處理orphan task



Job的種類:
Serial: 執行在單一node
Parallel: 執行在多個node上面
Interactive: 需要fast turnaround time
batch: 需要更多資源,不過不會立刻有response
(根據課本表示, workstation:cluster node 若等於2:1似乎是最佳比例)

Migration(遷移):
cluster size兩倍時,平行job的slowdown time會顯著降低
若node已經idle夠久,會被認為可以被migration




Load Sharing Facility(LSF):又稱工業軟體系統軟件,主要做為系統負載管理的系統。
本身利用平行化與序列處理的方式,來做job management與load sharing
本身可以用在cluster與grid上面,因此本身支援多種OS。
目的:提升系統的使用效率

MOSIX:
A distributed OS for linux clusters and clouds

MOSIX2:
Run as a virtualization layer in Linux
支援sequence及parallel application
可以在遠端執行application如同在本機端執行
native mode:藉由修改linux kernel以達到更好的效能

Memory-Ushering Algorithm
當本機端的main memory不足時,借用其他的cluster node的memory執行
藉由process migration的方式取代暫時paging或swapping到local disk的方法



----------------------------------------------------------------------------------------------------------------------
第三章: VM&virtualization cluster and data center

Virtualization: 將硬體利用軟體做模擬之,以建立一個虛擬的硬體設備,因此可以在單一硬體設備上有多個系統執行,藉此提升整體的Efficient
-->利用resources utilitation,來提升performance

The Virtualized System
透過額外的軟體達到virtualized system,建置出virtualizetion layer(又稱為hypervisor或virtual machine monitor)

Virtualization layer: 做為virtual & physical的接口,提供平台資源使用(將Hardware虛擬化)

五個virtualization的層級:
-Instruction set architecture(ISA) level
利用模擬ISA(指令集)達到virtualization
Dynamic binary translation:用code interpretation轉換ISA,指令可能為1 to 1或是1 to many轉換
-hardware level
藉由模擬硬體裝置,如產生虛擬的processors, memory, I/O device。因此可在單一設備上提供多人使用,以提升使用率,
此種為目前最常見的方式之一,EX: VMWare、Xen system
-operating system level
本身是會建置一個獨立的container(virtual hosting environment),藉此可以安裝系統,並可在其OS下增加額外的東西,EX: Jall、virtual Environment...
-library support level
很多application用的API並非host OS所有,可使用存在user-level的library支援guest OS程式的運作,是創造執行環境,而非使用VM在guest OS中執行
利用API hook控制communication link以模擬library
本層又稱user level application binary interface (ABI) 或API emulation
EX: WABI, lxrun, WINE, vCUDA, Visual MainWin
-User application level
於應用階段做虛擬化,雖然本身犧牲一些效能,但在底下開發出來的程式,
只需要對方有此虛擬平台即可,因此移植性高,經典例子為JAVA、.NET、Panot
因在OS中,application常以process執行,因此本層又叫process level



High level language (HLL) VMs
以應用程式的身份裝在OS之上的VM
EX: .NET CLR & Java virtual machine(JVM)

VMM的三個要求:
-上層使用之Device必須與在一般硬體上相同(完整模擬硬體環境)
-維持一定效能,不過由於本身是由軟體模擬出來的機制,
因此本身有一些overhead要負擔。雖然目前看來這部分有點弱
-在其上的OS必須能完整存取虛擬化後的資源(以利VM得以有完整功能)

Complete Control by a VMM
1.VMM要能分配resource
2.已分配的resource,VMM要能回收
3.沒分配出去的resource,程式就不能取用

Hardware-Assisted virtualization:
-並非所有process皆滿足這三個條件:
若系統不支援的部分,則需要管理者手動修改之。

為何要做OS-Level virtualization?
-在cluster環境中,可能有數百到數千個device
從hardware level做虛擬化太慢
-VM image的存放也是一個overhead
-hardware的虛擬化本身會降低部分校能,而且可能需要修改部分底層設定。
-->在OS-Level做虛擬化會比較有彈性。雖然看似個別獨立,不過本身是共用一個OS kernel,僅需要對個別使用者做差別性備份即可。



OS extension的優缺點
優:有最小的start up與shutdown cost、資源需求低、高scalability、VM可與host OS同步化
缺:在同一個host OS container只會有一種guest OS

VM resource partition
可以在一個host OS下開很多個VM,並將VM的resource access request重導向到VM的local resource partition
EX:多個VM存取同一個root dir



Virutal root directories(虛擬根目錄)
兩種實作方法:
-duplicating:不同的系統共享資源,但會造成嚴重的resource overhead
-sharing most resource:共享資源+部分私人資源



Middleware for virtualization
An overview of several library-level virtualization system



The vCUDA for virtualization
CUDA是programming model及library,使用GPU執行compute-intensive application,但CUDA在hardware level VM上難以直接執行
vCUDA模擬CUDA library,可安裝在guest OS,重導向CUDA API call至host OS
vCUDA採用client-server的模式,其中包含3元件:
1.vCUDA library
2.guest OS 中的virtual GPU(client)
3.host OS中的vCUDA stub(server)





The virtualization layer:
-hypervisor(又稱VMM) architecture
使guest OS得以在部分時候,利用hypercalls,藉以直接存取底層的資源
如此可以提升效率。EX: Xen
-para-virtualization
架構:在OS虛擬化的架構旁,另外執行一個「管理用」的OS,
用來管理整個I/O device driver,因此僅對CPU和catch做虛擬化,'
又稱「半虛擬化」
目的:用來降低虛擬化過程中的overhead。
並可改善guest OS kernel的performance,不過需要guest os相容
實做上使用intelligent compiler代替instraction by hypercalls

缺點:需要改寫部分OS指令,不一定能支援未被修改的OS
維護成本高(由於上一點)
效能改善有限,會隨者工作量變化(workload)而影響
-host-base virtualization
在host os上面再做一層虛擬化,不過到最下層硬體須要四次指令轉換
-->效率低落,實用性不高。




The hypervisor(就說是VMM了)
架在OS及hardware之間,為guest OS及其application提供hypercall
分為兩種:
micro-kernel hypervisor,僅提供基本的function
monolithic hypervisor,提供各種專用的function

Hardware virtualization:
-full virtualization
本身不修改host os
noncritical instruction不控制hardware,不影響系統安全,可直接在hardware執行
critical instruction較危險,需使用binary translation來做指令轉換,但轉換時會給系統很大的overhead,對於I/O bound的application很不利。也可利用記憶常用指令的方式改善效率,但會耗用更多memory
-host-base virtualization
建置在host OS之上,但host OS依然可管理hardware

----------------------------------------------------------------------------------------------------------------------------
(第二份投影片開始)
以下為老師飛也似時間





Hardware support for virtualization
-概念上是再處理process時,會在不同的state中做切換。
並根據hardware來做修改的virtualization。
-部分CPU不支援虛擬化;同理,利用修改CPU的設計,亦可提升虛擬化的效能

VMWare本身支援hybrid approach: 混合para-virtualization 與hardware-assisted virtualization(硬體加速模式),機動性調整以提升效能。

modern os 提供memory virtualization,本身是利用page table來做記憶體的虛擬化

I/O virtualization:
-full device emulation
-para-I/O-virtulization
-direct I/O

Four state of VMs:
-inactive(啟動前)
-active(啟動中)
-paused(暫停)
-suspanded(停止)



VM Live Migration:
-VM系統的熱插拔,主要做VM移植用,
-目的:降低移植時的overhead
-舊式做法:system完全停止->整體移植測試->再啟動
-Migration做法:
*先移植主體部分,此時原系統繼續執行

*再移植設定部分,此時僅需短暫停機即可。