文章來源于畢昇編譯 ,作者王哲葳
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsQTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iM3ADOyI2M0MmNxEzNiVmMzYzX1QTM1UTM0IzLclDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
項目簡介
-
項目名稱
畢昇Fortran編譯器内關聯态庫函數str_copy
-
項目描述
畢昇Fortran編譯器是一款基于classic flang的高性能Fortran編譯器,支援Fortran程式設計語言的編譯和運作,提供強大的數值計算和資料處理能力,在科學計算領域應用前景廣闊。f90_str_copy_klen是一個實作字元串拷貝功能的動态庫函數,本項目是對該動态庫函數進行内聯,預期提高編譯器字元串拷貝的性能。
-
項目導師
peixin-qiao
-
項目開發者
王哲葳,華東師範大學碩士在讀
-
項目連結
https://summer-ospp.ac.cn/#/org/prodetail/22b970386
開發詳情
01 方案描述
Flang編譯器主要由flang1和flang2兩個元件組成,其中flang1用于解析Fortran代碼并生成中間表示,然後通過flang2生成LLVM IR并輸出。本項目的主要任務就是在flang2中對解析出的“f90_str_copy_klen”函數進行内聯優化。這個項目的方案分為如下幾步:
步驟一
flang2會獲得通過Fortran生成的IR指令清單,周遊該清單,尋找到函數調用指令“I_CALL”。
步驟二
通過“I_CALL”指令的位置查詢所調用的是否為需要被内聯的函數,如本項目需要實作的“f90_str_copy_klen”函數的内聯。在确認需要内聯的函數後開始生成相應的指令,“f90_str_copy_klen”函數的内聯指令生成過程如下:
- 将複制後得到的字元串稱為目标字元串,待複制的字元串稱為輸入字元串。首先需要從原先的指令中獲得輸入字元串并開辟一系列記憶體空間用于記錄目标字元串、輸入字元串的起始位址、字元串索引及字元串長度。
- 對每一個輸入字元串,從頭開始周遊。分别判斷目前目标字元串、輸入字元串的索引是否小于其長度,如果均符合則将輸入字元串中對應索引的字元複制到目标字元串的相應位址中。如果輸入字元串索引大于等于其長度則處理下一個輸入字元串。如果目标字元串索引大于等于其長度則停止字元串的複制。
- 按照2所述流程依次周遊函數中的輸入字元串,直至所有字元串都完成複制。
- 目标字元串索引是否仍小于其長度,若是,則将目标字元串中剩餘未被指派的字元用空格進行補充。
- 将實作上述功能的指令替換掉對應的“I_CALL”指令。
步驟三
繼續flang2中的流程以生成對應的LLVM IR 檔案。
項目産出
- [√ ] 實作了項目方案中所需的功能。
-
[√ ] 分别用一個字元串、三個字元串作為輸入字元串,完成了共十種輸入字元串各種長度情況下”f90_str_copy_klen”函數内聯的的功能性測試,在這些輸入字元串中也包含了一些ASCII碼小于32(ASCII碼為32表示空格)的特殊字元。十種情況如下:
a=b
len(a) < len(b)
len(a) = len(b)
len(a) > len(b)
a = b // c // d
len(a) < len(b)
len(a) = len(b)
len(b) < len(a) < len(b) + len(c)
len(a) = len(b) + len(c)
len(b) + len(c) < len(a) < len(b) + len(c) + len(d)
len(a) = len(b) + len(c) + len(d)
len(a) > len(b) + len(c) + len(d)
- [√ ] 将“f90_str_copy_klen”在函數中調用一億次,對内聯前後所花費的時間做對比。實驗結果顯示沒有内聯時運作花費的時間約為10秒,内聯後運作花費的時間約為0.7秒。
-
測試代碼如下:
主函數:main.f90
program main
integer :: i
character(20) :: a, b, c, d
a = "aaaaaaaaaaaaaaa"
b = "aaaaaaaaaaaaaaa"
c = "aaaaaaaaaaaaaaa"
do i = 1, 100000000
call test(a, b, c, d, 20)
enddo
end
字元串拼接拷貝函數:test.f90
subroutine test(a, b, c, d, n)
integer :: n
character(n) :: a, b, c, d
d = a // b // c
end subroutine
-
測試方法如下:
未優化前:
$ flang main.f90 -c
$ flang test.f90 -O3 -c
$ flang main.o test.o -o a.out
$ time ./a.out
real 0m10.190s
user 0m10.180s
sys 0m0.004s
優化之後(編譯選項-Mx,218,0x1使能該優化功能):
$ flang main.f90 -c
$ flang test.f90 -O3 –c –Mx,218,0x1
$ flang main.o test.o -o a.out
$ time ./a.out