女人被狂躁到高潮视频免费无遮挡,内射人妻骚骚骚,免费人成小说在线观看网站,九九影院午夜理论片少妇,免费av永久免费网址

當(dāng)前位置:首頁(yè) > > 嵌入式IoT

D1 riscv芯片上運(yùn)行rt-thread進(jìn)行RVV性能評(píng)估


  • 概述

  • rt-thread在D1芯片上的移植

  • 如何開(kāi)啟D1&&D1s的rvv擴(kuò)展

  • RVV性能對(duì)比評(píng)估

  • RVV在RTOS如何使用的更好


概述

D1 && D1s(f133)采用的是平頭哥C906的core,上面已經(jīng)支持了RVV 0.7.1版本,雖然目前RVV1.0已經(jīng)frozen,這就意味著上游編譯器或者一些相關(guān)的生態(tài)軟件將支持RVV1.0,但是作為性能評(píng)估RVV0.7.1與RVV1.0影響并不大。下面的文章主要描述如何在D1 && D1s芯片上運(yùn)行rt-thread,并且描述如何開(kāi)啟RVV,同時(shí)對(duì)RVV性能進(jìn)行一個(gè)簡(jiǎn)單的評(píng)估,最后討論RVV如何與RTOS使用的問(wèn)題。

rt-thread在D1芯片上的移植

目前D1s有64MB的內(nèi)置DDR2,這非常適合運(yùn)行RTOS,所以將rtos移植到D1s上是非常不錯(cuò)的選擇。

其移植的細(xì)節(jié)不詳細(xì)介紹,可以查看源代碼

https://github.com/bigmagic123/d1-nezha-rtthread

移植的難點(diǎn)在于:

1.啟動(dòng),從芯片上電啟動(dòng)入口處跳轉(zhuǎn)到rt-thread入口處的匯編代碼

2.硬件串口的初始化,這里會(huì)涉及到時(shí)鐘配置

3.tick時(shí)鐘中斷,目前采用的是riscv的通用timer,需要配置clic

4.任務(wù)切換和上下文的保存與恢復(fù),這部分需要對(duì)入棧出棧的順序十分的清晰

5.串口中斷,這里需要弄清楚plic中斷處理機(jī)制

解決上述問(wèn)題,移植rt-thread將非常的簡(jiǎn)單,當(dāng)前的rt-thread運(yùn)行在M-mode,具有比較高的權(quán)限,可以隨意操作寄存器進(jìn)行配置。

編譯與運(yùn)行在windows和Linux上均可操作,主要參考如下的文檔:

https://github.com/bigmagic123/d1-nezha-rtthread/blob/main/README.md

目前已經(jīng)實(shí)現(xiàn)的功能有:

1.timer
2.uart
3.gpio
4.vector
5.FPU

如何開(kāi)啟D1&&D1s的rvv擴(kuò)展

想要使用RVV功能,需要開(kāi)啟VS標(biāo)志位,該位位于


VS位于MSTATUS寄存器的23到24位。但是需要注意的是,當(dāng)使用RVV時(shí),需要開(kāi)啟浮點(diǎn)寄存器(FS),不然會(huì)報(bào)錯(cuò)。

這部分在rt-thread的體現(xiàn)是在上下文切換的時(shí)候,需要將使用RVV的線程的MSTATUS設(shè)置成開(kāi)啟VS的模式。


可以VS設(shè)置b01。

只有當(dāng)使能該位,才能正常使用RVV指令,不然運(yùn)行會(huì)直接報(bào)錯(cuò)。

接著,編譯選項(xiàng)中還需要添加成如下選項(xiàng)

-march=rv64gcvxtheadc -mabi=lp64d -mtune=c906

這樣才能告訴編譯器支持RVV指令。

RVV性能對(duì)比評(píng)估

riscv 的RVV其編程模型主要有兩種方式,第一種采用rvv-intrinsic。這就是在編譯器中進(jìn)行intrinsic函數(shù)的構(gòu)建,可以將相關(guān)的rvv操作變成編輯器的內(nèi)置函數(shù)。采用類似下面的函數(shù)方式進(jìn)行編程。

vint8mf8_t vcopy_v_i8mf8 (vint8mf8_t src);
vint8mf4_t vcopy_v_i8mf4 (vint8mf4_t src);
...

其操作詳情可以參考:

https://github.com/riscv-non-isa/rvv-intrinsic-doc/

本質(zhì)上就是將復(fù)雜的匯編代碼操作換成C語(yǔ)言函數(shù)的形式,這種方式可讀性更強(qiáng)。rvv1.0后面也會(huì)提供這一種方式進(jìn)行。

第二種就是采用匯編進(jìn)行操作,裸寫匯編代碼的難度很大,但是可以實(shí)現(xiàn)比較好的優(yōu)化,這特別是在關(guān)鍵耗時(shí)的操作上進(jìn)行匯編級(jí)別的優(yōu)化,可以很大程度上提升程序運(yùn)行的性能。

在平頭哥開(kāi)源出來(lái)的GCC工具鏈中,并沒(méi)有rvv-intrinsic功能,所以只能通過(guò)匯編函數(shù)的方式進(jìn)行操作。

平頭哥開(kāi)源出來(lái)了一個(gè)神經(jīng)網(wǎng)絡(luò)的庫(kù),里面有C906的RVV底層操作。

https://github.com/T-head-Semi/csi-nn2

實(shí)現(xiàn)了一些基本的操作,抽象了各種常用的網(wǎng)絡(luò)層的接口,并且提供一系列已優(yōu)化的二進(jìn)制庫(kù)。

其主要的使用類似于CMSIS,Tensorflow等等。有了這些抽象接口,在使用RVV進(jìn)行特定優(yōu)化的時(shí)候,難度也會(huì)有所降低。

下面主要從csi-nn2抽取出vertor add,vertor mul,memcpy,也就是加法計(jì)算,乘法計(jì)算和內(nèi)存拷貝,三個(gè)方面,對(duì)其性能進(jìn)行評(píng)估。

https://github.com/bigmagic123/d1-nezha-rtthread/blob/main/bsp/d1-nezha/applications/vector.c

浮點(diǎn)數(shù)加法

采用向量操作

float a[10] = {1.2,1.3,1.4,1.5,1.6,1.7,1.8,2.0,2.1,2.2}; float b[10] = {1.2,1.3,1.4,1.5,1.6,1.7,1.8,2.0,2.1,2.2}; float c[10];
element_mul_f32(a, b, c, 10);

一次性處理10個(gè)元素,采用RVV向量的操作。

普通的加法

for(ii = 0; ii < 10; ii++)
{
 d[ii] = a[ii] + b[ii];
}

單個(gè)元素相加。

分別計(jì)算30000次。

最后的結(jié)果如下:


采用向量加法只需要7ms,而直接相加,則消耗了36ms,性能相差5倍左右。

浮點(diǎn)數(shù)相乘

與加法操作類似,也是一次性處理10個(gè)元素

float a[10] = {1.2,1.3,1.4,1.5,1.6,1.7,1.8,2.0,2.1,2.2}; float b[10] = {1.2,1.3,1.4,1.5,1.6,1.7,1.8,2.0,2.1,2.2}; float c[10];
element_mul_f32(a, b, c, 10);

普通的乘法

for(ii = 0; ii < 10; ii++)
{
 d[ii] = a[ii] * b[ii];
}

兩者性能對(duì)比


向量乘法也比普通的乘法性能強(qiáng)大一些,接近5倍的差別。

內(nèi)存拷貝

內(nèi)存拷貝的測(cè)試方法是測(cè)試rt_memcpy,memcpy,csi_c906_memcpy。分別代表rt-thread內(nèi)置的內(nèi)存拷貝函數(shù),采用C語(yǔ)言進(jìn)行實(shí)現(xiàn),memcpy是newlib庫(kù)函數(shù)的實(shí)現(xiàn),里面會(huì)對(duì)riscv架構(gòu)進(jìn)行優(yōu)化處理,csi_c906_memcpy則是采用向量操作,進(jìn)行內(nèi)存拷貝。

測(cè)試是先申請(qǐng)1MB的目標(biāo)內(nèi)存,1MB的源內(nèi)存,往源內(nèi)存中寫隨機(jī)數(shù)。

拷貝源內(nèi)存中的數(shù)據(jù)到目標(biāo)內(nèi)存,拷貝100次,也就是100M的內(nèi)存拷貝數(shù)據(jù)量。

結(jié)果如下:


顯然,內(nèi)存拷貝操作newlib中的memcpy性能是最佳的,而向量操作的memcpy反而其次,最差的是rt-thread的rt_memcpy。這里的原因是newlib的memcpy的是經(jīng)過(guò)優(yōu)化后的,而vector memcpy也可能是優(yōu)化的不好導(dǎo)致性能與newlib的memcpy相當(dāng)。rt-thread采用純C語(yǔ)言實(shí)現(xiàn),其通用性比較好,但是性能不佳。

RVV在RTOS如何使用的更好

這是一個(gè)關(guān)于更好的在RTOS上使用RVV的問(wèn)題,由于RTOS是為了追求實(shí)時(shí)性,一般來(lái)說(shuō),開(kāi)啟了FPU和RVV后,其寄存器的數(shù)量會(huì)非常的多,每次入棧和出棧的操作,如果每次都將全部的寄存器壓入和彈出,將會(huì)讓切換任務(wù)的時(shí)間變長(zhǎng),影響了系統(tǒng)的實(shí)時(shí)性。對(duì)于這種情況,其實(shí)可以利用mstatus中的VS和FS的標(biāo)志位進(jìn)行判斷。



在切換任務(wù)時(shí),可以通過(guò)這些標(biāo)識(shí),選擇是否壓棧和出棧,這樣保證了一部分性能實(shí)時(shí)性的情況下,也可以很好的處理FPU和RVV。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉