国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Linux|Centos|Ubuntu|系統(tǒng)進(jìn)程|Fedora|注冊(cè)表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服務(wù)器之家 - 服務(wù)器系統(tǒng) - Linux - 學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

2022-02-21 17:54commando_lwp Linux

這篇文章主要介紹了學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法,一起來學(xué)習(xí)下,大大提高數(shù)據(jù)運(yùn)算的效率。

本文跟著小編一起來學(xué)習(xí)在linux kernel態(tài)下如何使用neon對(duì)算法進(jìn)行加速的技巧,內(nèi)容通過圖文實(shí)例給大家做了詳細(xì)分析,一起來看下。

arm處理器從cortex系列開始集成neon處理單元,該單元可以簡單理解為協(xié)處理器,專門為矩陣運(yùn)算等算法設(shè)計(jì),特別適用于圖像、視頻、音頻處理等場(chǎng)景,應(yīng)用也很廣泛。

本文先對(duì)neon處理單元進(jìn)行簡要介紹,然后介紹如何在內(nèi)核態(tài)下使用neon,最后列舉實(shí)例說明。

一.neon簡介

其實(shí)最好的資料就是官方文檔,cortex™-a series programmer's guide ,以下描述摘自該文檔

1.1 simd

neon采用simd架構(gòu),single instruction multy data,一條指令處理多個(gè)數(shù)據(jù),neon中這多個(gè)數(shù)據(jù)可以很多,而且配置靈活(8bit、16bit、32bit為單位,可多個(gè)單位數(shù)據(jù)),這是優(yōu)勢(shì)所在。

如下圖,apu需要至少四條指令完成加操作,而neon只需要1條,考慮到ld和st,節(jié)省的指令更多。

 學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

上述特性,使neon特別適合處理塊數(shù)據(jù)、圖像、視頻、音頻等。

 1.2 neon architecture overview

neon也是load/store架構(gòu),寄存器為64bit/128bit,可形成向量化數(shù)據(jù),配合若干便于向量操作的指令。

1.2.1 commonality with vfp         1.2.2 data type

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

 指令中的數(shù)據(jù)類型表示,例如vmlal.s8:

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

1.2.3 registers 

32個(gè)64bit寄存器,d0~d31;同時(shí)可組成16個(gè)128 bit寄存器,q0~q15。與vfp公用。

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

寄存器內(nèi)部的數(shù)據(jù)單位為8bit、16bit、32bit,可以根據(jù)需要靈活配置。

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

neon的指令有normal,long,wide,narrow和saturating variants等幾種后綴,是根據(jù)操作的源src和dst寄存器的類型確定的。

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

   學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

1.2.4 instruction set

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

                     學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

1.3 neon 指令分類概述

指令比較多, 詳細(xì)可參考cortex™-a series programmer's guide。可大體分為:

neon general data processing instructions   neon shift instructions  neon logical and compare operations  neon arithmetic instructions neon multiply instructions  neon load and store element and structure instructions b.8 neon and vfp pseudo-instructions

簡單羅列一下各指令

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

                學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

                  學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

                學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

  學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

無循環(huán)左移,負(fù)數(shù)左移按右移處理。

load和store指令不太好理解,說明一下。

  學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

1.4 neon 使用方式      

1.4.1 neon使用方式

neon有若干種使用方式:

c語言被編譯器自動(dòng)向量化,需要增加編譯選項(xiàng),且c語言編碼時(shí)有若干注意事項(xiàng)。這種方式不確定性太大,沒啥實(shí)用價(jià)值   neon匯編,可行,匯編稍微復(fù)雜一點(diǎn),但是核心算法還是值得的   intrinsics,gcc和armcc等編譯器提供了若干與neon對(duì)應(yīng)的inline函數(shù),可直接在c語言里調(diào)用,這些函數(shù)反匯編時(shí)會(huì)直接編程響應(yīng)的neon指令。這種方式比較實(shí)用與c語言環(huán)境,且相對(duì)簡單。本文后續(xù)使用這種方式進(jìn)行詳細(xì)說明。          1.4.2  c語言neon數(shù)據(jù)類型

需包含arm_neon.h頭文件,該頭文件在gcc目錄里。都是向量數(shù)據(jù)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
typedef __builtin_neon_qi int8x8_t  __attribute__ ((__vector_size__ (8)));
typedef __builtin_neon_hi int16x4_t  __attribute__ ((__vector_size__ (8)));
typedef __builtin_neon_si int32x2_t  __attribute__ ((__vector_size__ (8)));
typedef __builtin_neon_di int64x1_t;
typedef __builtin_neon_sf float32x2_t  __attribute__ ((__vector_size__ (8)));
typedef __builtin_neon_poly8 poly8x8_t  __attribute__ ((__vector_size__ (8)));
typedef __builtin_neon_poly16 poly16x4_t  __attribute__ ((__vector_size__ (8)));
typedef __builtin_neon_uqi uint8x8_t  __attribute__ ((__vector_size__ (8)));
typedef __builtin_neon_uhi uint16x4_t  __attribute__ ((__vector_size__ (8)));
typedef __builtin_neon_usi uint32x2_t  __attribute__ ((__vector_size__ (8)));
typedef __builtin_neon_udi uint64x1_t;
typedef __builtin_neon_qi int8x16_t  __attribute__ ((__vector_size__ (16)));
typedef __builtin_neon_hi int16x8_t  __attribute__ ((__vector_size__ (16)));
typedef __builtin_neon_si int32x4_t  __attribute__ ((__vector_size__ (16)));
typedef __builtin_neon_di int64x2_t  __attribute__ ((__vector_size__ (16)));
typedef __builtin_neon_sf float32x4_t  __attribute__ ((__vector_size__ (16)));
typedef __builtin_neon_poly8 poly8x16_t  __attribute__ ((__vector_size__ (16)));
typedef __builtin_neon_poly16 poly16x8_t  __attribute__ ((__vector_size__ (16)));
typedef __builtin_neon_uqi uint8x16_t  __attribute__ ((__vector_size__ (16)));
typedef __builtin_neon_uhi uint16x8_t  __attribute__ ((__vector_size__ (16)));
typedef __builtin_neon_usi uint32x4_t  __attribute__ ((__vector_size__ (16)));
typedef __builtin_neon_udi uint64x2_t  __attribute__ ((__vector_size__ (16)));
 
typedef float float32_t;
typedef __builtin_neon_poly8 poly8_t;
typedef __builtin_neon_poly16 poly16_t;
 
typedef struct int8x8x2_t
{
 int8x8_t val[2];
} int8x8x2_t;
 
typedef struct int8x16x2_t
{
 int8x16_t val[2];
} int8x16x2_t;
 
typedef struct int16x4x2_t
{
 int16x4_t val[2];
} int16x4x2_t;
 
typedef struct int16x8x2_t
{
 int16x8_t val[2];
} int16x8x2_t;
 
typedef struct int32x2x2_t
{
 int32x2_t val[2];
} int32x2x2_t;
 
typedef struct int32x4x2_t
{
 int32x4_t val[2];
} int32x4x2_t;
 
typedef struct int64x1x2_t
{
 int64x1_t val[2];
} int64x1x2_t;
 
typedef struct int64x2x2_t
{
 int64x2_t val[2];
} int64x2x2_t;
 
typedef struct uint8x8x2_t
{
 uint8x8_t val[2];
} uint8x8x2_t;
 
typedef struct uint8x16x2_t
{
 uint8x16_t val[2];
} uint8x16x2_t;
 
typedef struct uint16x4x2_t
{
 uint16x4_t val[2];
} uint16x4x2_t;
 
typedef struct uint16x8x2_t
{
 uint16x8_t val[2];
} uint16x8x2_t;
 
typedef struct uint32x2x2_t
{
 uint32x2_t val[2];
} uint32x2x2_t;
 
typedef struct uint32x4x2_t
{
 uint32x4_t val[2];
} uint32x4x2_t;
 
typedef struct uint64x1x2_t
{
 uint64x1_t val[2];
} uint64x1x2_t;
 
typedef struct uint64x2x2_t
{
 uint64x2_t val[2];
} uint64x2x2_t;
 
typedef struct float32x2x2_t
{
 float32x2_t val[2];
} float32x2x2_t;
 
typedef struct float32x4x2_t
{
 float32x4_t val[2];
} float32x4x2_t;
 
typedef struct poly8x8x2_t
{
 poly8x8_t val[2];
} poly8x8x2_t;
 
typedef struct poly8x16x2_t
{
 poly8x16_t val[2];
} poly8x16x2_t;
 
typedef struct poly16x4x2_t
{
 poly16x4_t val[2];
} poly16x4x2_t;
 
typedef struct poly16x8x2_t
{
 poly16x8_t val[2];
} poly16x8x2_t;
 
typedef struct int8x8x3_t
{
 int8x8_t val[3];
} int8x8x3_t;
 
typedef struct int8x16x3_t
{
 int8x16_t val[3];
} int8x16x3_t;
 
typedef struct int16x4x3_t
{
 int16x4_t val[3];
} int16x4x3_t;
 
typedef struct int16x8x3_t
{
 int16x8_t val[3];
} int16x8x3_t;
 
typedef struct int32x2x3_t
{
 int32x2_t val[3];
} int32x2x3_t;
 
typedef struct int32x4x3_t
{
 int32x4_t val[3];
} int32x4x3_t;
 
typedef struct int64x1x3_t
{
 int64x1_t val[3];
} int64x1x3_t;
 
typedef struct int64x2x3_t
{
 int64x2_t val[3];
} int64x2x3_t;
 
typedef struct uint8x8x3_t
{
 uint8x8_t val[3];
} uint8x8x3_t;
 
typedef struct uint8x16x3_t
{
 uint8x16_t val[3];
} uint8x16x3_t;
 
typedef struct uint16x4x3_t
{
 uint16x4_t val[3];
} uint16x4x3_t;
 
typedef struct uint16x8x3_t
{
 uint16x8_t val[3];
} uint16x8x3_t;
 
typedef struct uint32x2x3_t
{
 uint32x2_t val[3];
} uint32x2x3_t;
 
typedef struct uint32x4x3_t
{
 uint32x4_t val[3];
} uint32x4x3_t;
 
typedef struct uint64x1x3_t
{
 uint64x1_t val[3];
} uint64x1x3_t;
 
typedef struct uint64x2x3_t
{
 uint64x2_t val[3];
} uint64x2x3_t;
 
typedef struct float32x2x3_t
{
 float32x2_t val[3];
} float32x2x3_t;
 
typedef struct float32x4x3_t
{
 float32x4_t val[3];
} float32x4x3_t;
 
typedef struct poly8x8x3_t
{
 poly8x8_t val[3];
} poly8x8x3_t;
 
typedef struct poly8x16x3_t
{
 poly8x16_t val[3];
} poly8x16x3_t;
 
typedef struct poly16x4x3_t
{
 poly16x4_t val[3];
} poly16x4x3_t;
 
typedef struct poly16x8x3_t
{
 poly16x8_t val[3];
} poly16x8x3_t;
 
typedef struct int8x8x4_t
{
 int8x8_t val[4];
} int8x8x4_t;
 
typedef struct int8x16x4_t
{
 int8x16_t val[4];
} int8x16x4_t;
 
typedef struct int16x4x4_t
{
 int16x4_t val[4];
} int16x4x4_t;
 
typedef struct int16x8x4_t
{
 int16x8_t val[4];
} int16x8x4_t;
 
typedef struct int32x2x4_t
{
 int32x2_t val[4];
} int32x2x4_t;
 
typedef struct int32x4x4_t
{
 int32x4_t val[4];
} int32x4x4_t;
 
typedef struct int64x1x4_t
{
 int64x1_t val[4];
} int64x1x4_t;
 
typedef struct int64x2x4_t
{
 int64x2_t val[4];
} int64x2x4_t;
 
typedef struct uint8x8x4_t
{
 uint8x8_t val[4];
} uint8x8x4_t;
 
typedef struct uint8x16x4_t
{
 uint8x16_t val[4];
} uint8x16x4_t;
 
typedef struct uint16x4x4_t
{
 uint16x4_t val[4];
} uint16x4x4_t;
 
typedef struct uint16x8x4_t
{
 uint16x8_t val[4];
} uint16x8x4_t;
 
typedef struct uint32x2x4_t
{
 uint32x2_t val[4];
} uint32x2x4_t;
 
typedef struct uint32x4x4_t
{
 uint32x4_t val[4];
} uint32x4x4_t;
 
typedef struct uint64x1x4_t
{
 uint64x1_t val[4];
} uint64x1x4_t;
 
typedef struct uint64x2x4_t
{
 uint64x2_t val[4];
} uint64x2x4_t;
 
typedef struct float32x2x4_t
{
 float32x2_t val[4];
} float32x2x4_t;
 
typedef struct float32x4x4_t
{
 float32x4_t val[4];
} float32x4x4_t;
 
typedef struct poly8x8x4_t
{
 poly8x8_t val[4];
} poly8x8x4_t;
 
typedef struct poly8x16x4_t
{
 poly8x16_t val[4];
} poly8x16x4_t;
 
typedef struct poly16x4x4_t
{
 poly16x4_t val[4];
} poly16x4x4_t;
 
typedef struct poly16x8x4_t
{
 poly16x8_t val[4];
} poly16x8x4_t;

 1.4.3  gcc的neon函數(shù)

跟neon指令對(duì)應(yīng),詳見gcc手冊(cè)。

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

 二.內(nèi)核狀態(tài)下使用neon的規(guī)則

在linux里,應(yīng)用態(tài)可以比較方便使用neon instrinsic,增加頭arm_neon.h頭文件后直接使用。但是內(nèi)核態(tài)下使用neon有較多限制,在linux內(nèi)核文檔  /documentation/arm/kernel_mode_neon.txt對(duì)此有詳細(xì)說明。要點(diǎn)為:

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

 還有一點(diǎn)特別關(guān)鍵:

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

?
1
2
3
4
5
6
cc [m] /work/platform-zynq/drivers/zynq_fpga_driver/mmi_neon/lcd_hw_fs8812_neon.o
in file included from /home/liuwanpeng/lin/lib/gcc/arm-xilinx-linux-gnueabi/4.8.3/include/arm_neon.h:39:0,
         from /work/platform-zynq/drivers/zynq_fpga_driver/mmi_neon/lcd_hw_fs8812_neon.c:8:
/home/liuwanpeng/lin/lib/gcc/arm-xilinx-linux-gnueabi/4.8.3/include/stdint.h:9:26: error: no include path in which to search for stdint.h
 # include_next <stdint.h>
 沒有使用-ffreestanding編譯選項(xiàng)時(shí),在內(nèi)核態(tài)下使用出現(xiàn)此編譯錯(cuò)誤。

 三.實(shí)例

neon一般在圖像等領(lǐng)域,最小處理單位就是8bit,而不是1bit,這方便的例子非常多,本文就不說明了。在實(shí)際項(xiàng)目中,我需要對(duì)液晶的一組數(shù)據(jù)按位操作,變換,形成新的數(shù)據(jù),如果用傳統(tǒng)arm指令,掩碼、移位、循環(huán),想想效率就非常低。于是決定使用neon的位相關(guān)指令完成上述任務(wù)。

3.1 任務(wù)說明

如下圖,需要對(duì)各個(gè)bit進(jìn)行轉(zhuǎn)換,組成新的數(shù)據(jù)。

 學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

3.2 算法說明

使用vmsk、vshl、vadd等位操作完成。

3.3 kernel配置

必須配置內(nèi)核支持neon,否則kernel_neon_begin()和kernel_neon_end()等函數(shù)不會(huì)編輯進(jìn)去。

make menuconfig:floating point emulation,如下圖。

學(xué)習(xí)在kernel態(tài)下使用NEON對(duì)算法進(jìn)行加速的方法

?
1
2
3
未使能“support for neon in kernel mode”時(shí)會(huì)報(bào)錯(cuò):
mmi_module_amp: unknown symbol kernel_neon_begin (err 0)
mmi_module_amp: unknown symbol kernel_neon_end (err 0)

3.4 模塊代碼

由于neon代碼需要單獨(dú)設(shè)置編譯選項(xiàng),所以單獨(dú)建立了一個(gè)內(nèi)核模塊,makefile如下:

?
1
cflags_module += -o3 -mfpu=neon -mfloat-abi=softfp -ffreestanding 

核心代碼:

?
1
2
3
#include <linux/module.h>
#include <linux/printk.h>
#include <arm_neon.h>  // 來自gcc的頭文件,必須用-ffreestanding編譯選徐昂

#define lcd_8812_row_bytes 16
#define lcd_8812_page_rows 8
#define lcd_page_bytes (lcd_8812_row_bytes*lcd_8812_page_rows)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
int fs8812_cvt_buf( uint8 * dst, uint8 * src )
{
 
  uint8x16_t v_src[8];
  uint8x16_t v_tmp[8];
  uint8x16_t v_dst[8];
  uint8x16_t v_msk;
  int8x16_t v_shift;
  int8 rshl_bits[8] = {0,1,2,3,4,5,6,7};
  int8 row,bit;
  uint8 page;
  uint8 * fb_page_x = null; 
 
  // convert the frame_buf for fs8812
  for( page=0;page<4;page++ ){
    fb_page_x = src + page*lcd_page_bytes;
    for( row=0;row<lcd_8812_page_rows;row++ )
      v_src[row] = vld1q_u8( fb_page_x + row*lcd_8812_row_bytes );
       for( bit=0;bit<8;bit++){
        v_msk = vdupq_n_u8(1<<bit);
        for( row=0;row<lcd_8812_page_rows;row++){
          v_tmp[row] = vandq_u8(v_src[row],v_msk);  // only process the desire bit
          v_shift = vdupq_n_s8( rshl_bits[row]-bit );
          v_tmp[row] = vshlq_u8( v_tmp[row],v_shift );
        } 
        v_dst[bit] = vorrq_u8(v_tmp[0],v_tmp[1]);   // all bit_x convert to one row
        v_dst[bit] |= vorrq_u8(v_tmp[2],v_tmp[3]);
        v_dst[bit] |= vorrq_u8(v_tmp[4],v_tmp[5]);
        v_dst[bit] |= vorrq_u8(v_tmp[6],v_tmp[7]);       
      }
      // store to ram
      fb_page_x = dst + page*lcd_page_bytes;
      for( row=0;row<lcd_8812_page_rows;row++ ){
         vst1q_u8(fb_page_x,v_dst[row]);
        fb_page_x += lcd_8812_row_bytes;
      }
  }
  return 0;
}
 
export_symbol_gpl(fs8812_cvt_buf);

調(diào)用模塊,務(wù)必沒有“-mfpu=neon -mfloat-abi=softfp ”選項(xiàng)

?
1
2
3
4
// convert the frame_buf for fs8812
kernel_neon_begin();
fs8812_cvt_buf( g_tmp_buf, frame_buf );
kernel_neon_end();

 以上就是本篇文章的全部內(nèi)容,大家有不懂的可以在下面留言區(qū)討論。

原文鏈接:https://www.cnblogs.com/liuwanpeng/p/7833000.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩欧美三级在线观看 | 四虎最新网址 | 99国产精品久久久久久久久久 | 天天操人人干 | 7799精品视频| 91精彩视频在线观看 | 99青草 | 成人午夜精品久久久久久久蜜臀 | 91在线免费视频 | 一区二区国产在线观看 | 日韩在线视频观看 | 日本一区二区三区免费观看 | 综合久久久 | 国产黄色片免费 | 这里只有精品在线视频观看 | 免费毛片网站 | 国产精品视频网 | 国产欧美高清在线观看 | 日韩精品专区 | 中文字幕乱码亚洲精品一区 | 国产日韩一区二区 | 一区二区三区日韩 | 国产日韩欧美在线 | 国产中文字幕在线播放 | 97超碰免费| 久久精品无码一区二区日韩av | 日韩精品一区二区三区av | 一级色视频 | 国产一区视频在线看 | 欧美一区二区免费 | 99久久夜色精品国产亚洲1000部 | 日韩欧美国产精品 | 久久久免费视频看看 | 91精品久久久久久久久久 | 红桃成人少妇网站 | 国产成人在线视频 | 欧美在线播放一区 | 国产精品久久久久久久岛一牛影视 | 午夜久久久 | 欧美1区2区3区 | 日本久久网 |