544 eff.c 1761 優化設計文檔

1:性能分析

1.1性能對比

oneapi 與hygonGcc性能對比發現,544課題中的eff.c 1761循環處,oneapi 進行了循環向量化, gcc使用標量,循環源碼前加 #pragma clang loop vectorize(disable) 找出oneapi在該循環處關閉和開啟loop vect 的性能差距,在15%左右。

? mme34.0.svg(圖中的svml_log4_mask)

1.2源代碼

1761           for (k = 0; k < lpears[i] + upears[i]; k++) {
1762
1763             if (pearlist[i] == NULL) {
1764                fprintf(nabout,
1765                        "NULL pair list entry in egb loop 1, taskid = %d\n",
1766                        mytaskid);
1767                fflush(nabout);
1768             }
1769             j = pearlist[i][k];
1770
1771             xij = xi - x[dim * j];
1772             yij = yi - x[dim * j + 1];
1773             zij = zi - x[dim * j + 2];
1774             r2 = xij * xij + yij * yij + zij * zij;
1775
1776             if (dim == 4) {                     // delete
1777                wij = wi - x[dim * j + 3];
1778                r2 += wij * wij;
1779             }
1780
1781             if (r2 > rgbmaxpsmax2)      //  %hir.cmp.4310 ule
1782                continue;
1783             dij1i = 1.0 / sqrt(r2);
1784             dij = r2 * dij1i;
1785             sj = fs[j] * (rborn[j] - BOFFSET);   //   select fast
1786             sj2 = sj * sj;
1787
1788             /*
1789              * ---following are from the Appendix of Schaefer and Froemmel,
1790              * JMB 216:1045-1066, 1990;  Taylor series expansion for d>>s
1791              * is by Andreas Svrcek-Seiler; smooth rgbmax idea is from
1792              * Andreas Svrcek-Seiler and Alexey Onufriev.
1793              */
1794
1795             if (dij > rgbmax + sj)      // rgbmax = 20;   %hir.cmp.4333 ule
1796                continue;
1797
1798             if ((dij > rgbmax - sj)) {      //    %hir.cmp.4349  ogt
1799                uij = 1. / (dij - sj);
1800                sumi -= 0.125 * dij1i * (1.0 + 2.0 * dij * uij +
1801                                         rgbmax2i * (r2 -
1802                                                     4.0 * rgbmax *
1803                                                     dij - sj2) +
1804                                         2.0 * log((dij - sj) * rgbmax1i));
1805
1806             } else if (dij > 4.0 * sj) {
1807                dij2i = dij1i * dij1i;
1808                tmpsd = sj2 * dij2i;
1809                dumbo =
1810                    TA + tmpsd * (TB +
1811                                  tmpsd * (TC +
1812                                           tmpsd * (TD + tmpsd * TDD)));
1813                sumi -= sj * tmpsd * dij2i * dumbo;
1814
1815             } else if (dij > ri + sj) {
1816                sumi -= 0.5 * (sj / (r2 - sj2) +
1817                               0.5 * dij1i * log((dij - sj) / (dij + sj)));
1818
1819             } else if (dij > fabs(ri - sj)) {
1820                theta = 0.5 * ri1i * dij1i * (r2 + ri * ri - sj2);
1821                uij = 1. / (dij + sj);
1822                sumi -= 0.25 * (ri1i * (2. - theta) - uij +
1823                                dij1i * log(ri * uij));
1824
1825             } else if (ri < sj) {
1826                sumi -= 0.5 * (sj / (r2 - sj2) + 2. * ri1i +
1827                               0.5 * dij1i * log((sj - dij) / (sj + dij)));
1828
1829             }
1830
1831          }

2 向量化 遇到的問題

2.1 if printf

               if (pearlist[i] == NULL) {
1764                fprintf(nabout,
1765                        "NULL pair list entry in egb loop 1, taskid = %d\n",
1766                        mytaskid);
1767                fflush(nabout);
1768             }j = pearlist[i][k];

問題:分析不出內存關系,無法ifcvt。引入了控制流,否則control flow in loop。

eff.c:2072:16: missed: statement clobbers memory: fprintf (nabout.934_2047, "NULL pair list entry in egb loop 1, taskid = %d\n", 0);

解決辦法:循環無關的判斷,若 pearlist[i] == NULL 則求j = pearlist[i][k]為非法,按照邏輯在if判斷里面插入abort()(AOCC 插入了),符合邏輯同時 loop unswitch 可以將其提到循環外

2.2 ifcvt pass?

ifcvt pass 是loop vect pass 的必須經過的前置pass, 二者綁定,中間一般不能插入其他pass , 目的為了對if else 分支做conversion , 將分支跳轉轉化為條件選擇,以便于做 loop vect.

對于if else 的結構,ifcvt pass可以將其轉化為由原來 多個控制流和bb塊的形式,消除控制流合并到到同一個bb塊,通過條件運算符?或者 mask_load的方式,使其滿足loop vect? pass 的 loop form analysis。最內層的loop只能由兩個bb塊組成的要求,進而進行下一步的loop vect。

ifcvt 消除if中的control flow。

/* Predicate each write to memory in LOOP.
2401
2402    This function transforms control flow constructs containing memory
2403    writes of the form:
2404
2405    | for (i = 0; i < N; i++)
2406    |   if (cond)
2407    |     A[i] = expr;
2408
2409    into the following form that does not contain control flow:
2410
2411    | for (i = 0; i < N; i++)
2412    |   A[i] = cond ? expr : A[i];

2.3 dim =3 常量傳播

1776             if (dim == 4) {
1777                wij = wi - x[dim * j + 3];
1778                r2 += wij * wij;
1779             }

問題:wij的計算會向量化遇到問題。

解決辦法:由于dim 是靜態全局變量,嘗試過inline 做常量傳播,發現并未能實現。調整loop unswitch 參數--param=max-unswitch-insns=150,將其提到循環外面。

2.4? ?phi 節點的參數超過限制

問題:sumi 的結果的phi節點參數過多,無法進行ifcvt

BB 90 has complicated PHI with more than 4 args.

解決:aggressive_if_conv = true; 讓ifcvt 做激進的優化,不受phi節點參數個數限制。

3300   /* Apply more aggressive if-conversion when loop or its outer loop were
3301      marked with simd pragma.  When that's the case, we try to if-convert
3302      loop containing PHIs with more than MAX_PHI_ARG_NUM arguments.  */
3303  // aggressive_if_conv = loop->force_vectorize;
3304   aggressive_if_conv = true;
3305   if (!aggressive_if_conv)
3306     {
3307       class loop *outer_loop = loop_outer (loop);
3308       if (outer_loop && outer_loop->force_vectorize)
3309   aggressive_if_conv = true;
3310     }

2.5? gcc在zen架構下,不支持mask gather

1769             j = pearlist[i][k];
1781             if (r2 > rgbmaxpsmax2)      
1782                continue;
1783             dij1i = 1.0 / sqrt(r2);
1784             dij = r2 * dij1i;
1785             sj = fs[j] * (rborn[j] - BOFFSET); 
1786             sj2 = sj * sj;

問題:對于每一輪的j 的值 是不連續的,因此fs[j] 也不連續, 并且在if continue 之后需要進行mask, 不支持使用mask從不連續的內存向量化的取數據。

467 /* X86_TUNE_USE_GATHER_4PARTS: Use gather instructions for vectors with 4
468    elements.  */
469 /*DEF_TUNE (X86_TUNE_USE_GATHER_4PARTS, "use_gather_4parts",
470     ~(m_ZNVER1 | m_ZNVER2 | m_ZNVER3 | m_ZNVER4 | m_ALDERLAKE | m_GENERIC))*/

解決方法:可以使用-mtune-ctrl=use_gather_4parts 使其支持builtin 形式的mask gather操作。

2.6 多分支下的同一個reduction var 問題

問題:nphi_def_loop_uses >?1 一個reduction 變量在loop 中使用次數超過一個,被認為不是simple reduction 。loop vect pass 不會對其向量化。

69628 eff.c:1761:24: note:   Analyze phi: sumi_1654 = PHI <sumi_1557(320), 0.0(402)>69629 eff.c:1761:24: missed:   reduction used in loop.

解決辦法:在ifcvt pass 中加上一個函數,實現如下述源碼中的,將同一個reduction 變為多個不同的reduction ,實現向量化。

    
1763          double temp0 = 0;
1764          double temp1 = 0;
1765          double temp2 = 0;
1766          double temp3 = 0;
1767          double temp4 = 0;
1805 
1806             if ((dij > rgbmax - sj)) {
1807                uij = 1. / (dij - sj);
1808             
1813             /*   sumi -= 0.125 * dij1i * (1.0 + 2.0 * dij * uij +
1814                                         rgbmax2i * (r2 -
1815                                                     4.0 * rgbmax *
1816                                                     dij - sj2) +
1817                                         2.0 * log((dij - sj) * rgbmax1i));*/
1818            
1823                temp0 -= 0.125 * dij1i * (1.0 + 2.0 * dij * uij +
1824                                         rgbmax2i * (r2 -
1825                                                     4.0 * rgbmax *
1826                                                     dij - sj2) +
1827                                         2.0 * log((dij - sj) * rgbmax1i));
1828 
1829             } else if (dij > 4.0 * sj) {
1830                dij2i = dij1i * dij1i;
1831                tmpsd = sj2 * dij2i;
1832                dumbo =
1833                    TA + tmpsd * (TB +
1834                                  tmpsd * (TC +
1835                                           tmpsd * (TD + tmpsd * TDD)));
1836           
1837           //     sumi -= sj * tmpsd * dij2i * dumbo;
1839                temp1 -= sj * tmpsd * dij2i * dumbo;
1840 
1841             } 
1879          sumi = temp0 + temp1 + temp2+ temp3+temp4;
1880 

能夠實現向量化,但是性能相對與標量下降了

544base向量化加上分塊
32 copies10092107

?向量化的代價太大,臨時變量,mask gather load帶來的性能下降太顯著。(性能下降的loop vect 為什么能通過,cost的計算,沒有把mask gather 算進去)。

3. 向量化后優化

3.1:循環分塊

問題:gcc 向量化后所有分支的代碼在一個bb塊里面,所以所有的分支都會走一遍,對最后運算的結果根據分支條件進行選擇,帶來冗余運算。

解決方法:發現gcc loop pass 上有對optimize_mask_stores,向量化后進行分塊的函數。在此基礎上拓展添加了對 VEC_COND_EXPR的分塊。

添加對于每個分支判斷變量全為0,也就是所有元素都不滿足該分支,則不需要進入該分支計算,省去了以部分冗余運算。

3.2:向量化因子

使用該選擇? -mtune-ctrl=^avx256_split_regs,^avx128_optimal,256_unaligned_store_optimal 打開256非對其存儲優化,可以使VF 由 4 變為8, 提高性能。

544baseVF4VF8
32 copies100101107

4:優化詳細說明

4.1 添加的編譯選項

--param=max-unswitch-insns=150 -ftree-insert-abort
-mtune-ctrl=^avx256_split_regs,^avx128_optimal,256_unaligned_store_optimal,use_gather_4parts

1:loop unswitch? insns 參數調整,默認是50,調整到150

2:插入一個新的pass 來插入abort()

3: 使能256bit的非對齊存儲優化,VF為8.(^avx256_split_regs 不加這個也可)

4:使能256bit 的 mask gather 指令。

4.2:添加的優化代碼

4.2.1 激進的ifcvt優化 (找到選項來控制)?

將?aggressive_if_conv 標志位修改為true。(能否通過某些選項來控制)

3303  // aggressive_if_conv = loop->force_vectorize;
3304   aggressive_if_conv = true;

4.2.2? 插入abort() 優化

新建一個gimple pass,? 放在adjust_alignment pass 后。(107 pass)

199   NEXT_PASS (pass_adjust_alignment);
200   NEXT_PASS (pass_insert_abort);
201   NEXT_PASS (pass_all_optimizations);

設計思路:識別對0進行判斷gimple_cond,并且判斷為true的bb 以及其single suc,有對該gimple cond lhs 定義的stmt進行解引用,則認為是對空指針解引用回出現問題,插入abort()

識別的pattern:

(1) :識別一個gimple_cond 語句,并且是和0進行相等判斷

(2) :找到判斷為true的bb塊以及其后繼bb塊中,是否有對該判斷條件lhs的def的stmt進行解引用使用。

transform:

(1):找到后在gimple cond條件為true的bb 末尾插入abort()。

14044   <bb 148> [local count: 919275880]:
14045   _2044 = _127 + _2039;
14046   _2045 = *_2044;
14047   if (_2045 == 0B)
14048     goto <bb 149>; [17.43%]
14049   else
14050     goto <bb 150>; [82.57%]
14051
14052   <bb 149> [local count: 160229786]:
14053   _2046 = 0;
14054   _2047 = nabout;
14055   fprintf (_2047, "NULL pair list entry in egb loop 1, taskid = %d\n", _2046);
14056   _2048 = nabout;
14057   fflush (_2048);
14058
14059   <bb 150> [local count: 919275880]:
14060   _2049 = *_2044;
14061   _2051 = (long unsigned int) k_2050;
14062   _2052 = _2051 * 4;
14063   _2053 = _2049 + _2052;
14064   j_2054 = *_2053;

4.2.3 消除reduction use in loop (改變一種方式,消除reduction,重新修改代碼),如果是sumi的加減混合運算?

使用其他方法修改reduction 后性能沒有原方法好,因為原方法都是在循環外面,新方法需要在循環里面。

在ifcvt pass 中添加函數,(嘗試在loop vect pass 中當出現reduction use in loop? 后transform , 新建的reduction 會錯過 loop vect 中對reduction 的分析)

思路:識別reduction? 在 loop 中的使用次數超過1次的情況,找到該reduction 的phi 節點,在每次使用的地方進行替換成為不同的reduction,需要對是否進行ifcvt的兩個版本都進行轉化。標量和向量版本都會走到(如何識別是reduction?)? ? ? ?復用發現reduction 的接口,在一個新的pass 里面加上這部分代碼。

(該優化是根據先修改源碼后,產生的IR,進行對照修改,涉及到的修改較多,目前想僅僅針對該課題pattern,其他情況比較難以覆蓋)

1761           for (k = 0; k < lpears[i] + upears[i]; k++) {
1762
1763             if (pearlist[i] == NULL) {
1764                fprintf(nabout,
1765                        "NULL pair list entry in egb loop 1, taskid = %d\n",
1766                        mytaskid);
1767                fflush(nabout);
1768             }
1769             j = pearlist[i][k];
1770
1771             xij = xi - x[dim * j];
1772             yij = yi - x[dim * j + 1];
1773             zij = zi - x[dim * j + 2];
1774             r2 = xij * xij + yij * yij + zij * zij;
1775
1776             if (dim == 4) {                     // delete
1777                wij = wi - x[dim * j + 3];
1778                r2 += wij * wij;
1779             }
1780
1781             if (r2 > rgbmaxpsmax2)      //  %hir.cmp.4310 ule
1782                continue;
1783             dij1i = 1.0 / sqrt(r2);
1784             dij = r2 * dij1i;
1785             sj = fs[j] * (rborn[j] - BOFFSET);   //   select fast
1786             sj2 = sj * sj;
1787
1788             /*
1789              * ---following are from the Appendix of Schaefer and Froemmel,
1790              * JMB 216:1045-1066, 1990;  Taylor series expansion for d>>s
1791              * is by Andreas Svrcek-Seiler; smooth rgbmax idea is from
1792              * Andreas Svrcek-Seiler and Alexey Onufriev.
1793              */
1794
1795             if (dij > rgbmax + sj)      // rgbmax = 20;   %hir.cmp.4333 ule
1796                continue;
1797             double temp = 0;
1798             if ((dij > rgbmax - sj)) {      //    %hir.cmp.4349  ogt
1799                uij = 1. / (dij - sj);
1800                temp -= 0.125 * dij1i * (1.0 + 2.0 * dij * uij +
1801                                         rgbmax2i * (r2 -
1802                                                     4.0 * rgbmax *
1803                                                     dij - sj2) +
1804                                         2.0 * log((dij - sj) * rgbmax1i));
1805
1806             } else if (dij > 4.0 * sj) {
1807                dij2i = dij1i * dij1i;
1808                tmpsd = sj2 * dij2i;
1809                dumbo =
1810                    TA + tmpsd * (TB +
1811                                  tmpsd * (TC +
1812                                           tmpsd * (TD + tmpsd * TDD)));
1813                temp -= sj * tmpsd * dij2i * dumbo;
1814
1815             } else if (dij > ri + sj) {
1816                temp -= 0.5 * (sj / (r2 - sj2) +
1817                               0.5 * dij1i * log((dij - sj) / (dij + sj)));
1818
1819             } else if (dij > fabs(ri - sj)) {
1820                theta = 0.5 * ri1i * dij1i * (r2 + ri * ri - sj2);
1821                uij = 1. / (dij + sj);
1822                temp -= 0.25 * (ri1i * (2. - theta) - uij +
1823                                dij1i * log(ri * uij));
1824
1825             } else if (ri < sj) {
1826                temp -= 0.5 * (sj / (r2 - sj2) + 2. * ri1i +
1827                               0.5 * dij1i * log((sj - dij) / (sj + dij)));
1828
1829             }sumi+=temp;
1830
1831          }
進行ifcvt后的部分(向量)(初始化為0,不為0 的情況 應該直接將其初始化結果加入到新建的reduction 變量中)

(1):在loop header bb 中識別phi stmt,找到其lhs中使用次數等于該分支數量,并且初始化為0的phi stmt。

transfrom:?

(1):新建與分支數量相等的phi stmt ,初始值為0和該循環計算后的結果,作為一個新的reduction.

? (2)? :? ?新建該reduction 和 每個分支運算結果的gimple assign。

(3):對最后結果累加運算。

48399   # k_1747 = PHI <k_2147(234), 0(279)>                                                      
48400   # sumi_1470 = PHI <sumi_2753(234), 0.0(279)>                                                
48401   # RANGE [0, 2147483647] NONZERO 2147483647  48488   sumi_2087 = sumi_1470 + _2085;
48489   _3187 = dij_2056 <= _2068;48507   sumi_2102 = sumi_1470 - _2101;
48508   _3169 = dij_2056 <= _2088;
48509   _3168 = _3169 & _3184;

轉化為:

 51162   # temp_value.1035_2087 = PHI <tmp_var.1036_2090(320), 0.0(402)>
51164   # temp_value.1043_2073 = PHI <tmp_var.1044_2063(320), 0.0(402)>51320   _ifc__2108 = _1303 ? _1605 : 0.0;51321   tmp_var.1036_2090 = _ifc__2108 + temp_value.1035_2087;
51324   _ifc__2064 = _1315 ? _1586 : 0.0;51325   tmp_var.1044_2063 = _ifc__2064 + temp_value.1043_2073;52177   # tmp_sumi.1045_2075 = PHI <tmp_var.1044_2063(304), tmp_sumi_2.1060_2061(399)>52175   # tmp_sumi.1037_2076 = PHI <tmp_var.1036_2090(304), tmp_sumi_2.1056_2057(399)>52190   # sumi_suc.1046_2042 = PHI <tmp_sumi.1045_2075(351), 0.0(74), tmp_sumi.1074_644(352)>52188   # sumi_suc.1038_2775 = PHI <tmp_sumi.1037_2076(351), 0.0(74), tmp_sumi.1068_704(352)>
52193   _2052 = sumi_suc.1038_2775 + sumi_suc.1046_2042;
不進行ifcvt的部分(標量)

transform:?

(1):新建phi stmt 初始化為0,與分支數量相同。

(2):修改每個分支的中間運算結果。

(3):對每個分支的結果用phi節點來控制。

 # sumi_3078 = PHI <0.0(280), sumi_2855(277)>sumi_2872 = sumi_3078 + _2911;sumi_2973 = sumi_3078 - _2974;sumi_2855 = PHI <sumi_3078(261), sumi_3078(263), sumi_3078(269), sumi_3016(271), sumi_2999(272), sumi_2988(273), sumi_2973(274), sumi_2872(275)>

轉化為:

 51867   # temp_value_2.1081_596 = PHI <0.0(426), tmp_sumi_2.1082_597(423)>51868   # temp_value_2.1083_598 = PHI <0.0(426), tmp_sumi_2.1084_575(423)>sumi_1004 = temp_value_2.1081_596 + _1003;sumi_866 = temp_value_2.1083_598 - _865;# tmp_sumi_2.1082_597 = PHI <temp_value_2.1081_596(407),temp_value_2.1081_596(409),temp_value_2.1081_596(412),temp_value_2.1081_596(414), temp_value_2.1081_596(416),temp_value_2.1081_596(418),temp_value_2.1081_596(419), sumi_1004(421)># tmp_sumi_2.1084_575 = PHI <temp_value_2.1083_598(407), temp_value_2.1083_598(409), temp_value_2.1083_598(412), temp_value_2.1083_598(414), temp_value_2.1083_598(416), temp_value_2.1083_598(418), sumi_866(419), temp_value_2.1083_598(421)>

4.2.4 if else / if continue 向量化后分塊優化? ?(添加cost計算?)

targetm.vectorize.empty_mask_is_expensive

aarch64_empty_mask_is_expensive? 這里不做mask_store 的

default_empty_mask_is_expensive? 其他情況都會進行

26378 /* Implement TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE.  Assume for now that
26379    it isn't worth branching around empty masked ops (including masked
26380    stores).  */
26381
26382 static bool
26383 aarch64_empty_mask_is_expensive (unsigned)
26384 {
26385   return false;
26386 }

仿照loop vect pass 中的optimize_mask_stores,在loop vect pass 中 加上基于vec_cond_expr分塊的函數

思路:(1)識別loop 中在同一個bb 中的 VEC_COND_EXPR,

(2)根據第二個參數找到每個分支最后計算的結果,從此處開始拆分bb。

(3)根據第一個參數mask,找到每個分支條件,將這兩個mask相或,在此后新建一個該或結果與0進行比較的gimple_cond,插入到分支條件后,同時新建該結果判斷為ture 和 false的edge,分別指向新建的bb和其下一個bb。

(4)在拆分bb 塊后面新建一個空 bb ,并且gimple_cond 之后的stmt 移動到新建的bb 中,維護其edge,指向下一個bb.

 98615   vect__ifc__2106.1217_795 = VEC_COND_EXPR <mask__1612.1193_854, vect__1541.1206_870, { 0.0, 0.0, 0.0, 0.0 }>;98616   vect__ifc__2106.1217_796 = VEC_COND_EXPR <mask__1612.1193_821, vect__1541.1206_871, { 0.0, 0.0, 0.0, 0.0 }>; 98621   vect__ifc__2706.1220_803 = VEC_COND_EXPR <mask__1617.1210_879, vect__1555.1216_792, { 0.0, 0.0, 0.0, 0.0 }>;98622   vect__ifc__2706.1220_804 = VEC_COND_EXPR <mask__1617.1210_880, vect__1555.1216_793, { 0.0, 0.0, 0.0, 0.0 }>; 

? ? ? ?

? ? ? ? ?

5.其他優化探索

5.1帶有mask的向量數學函數

在loop vect pass 后新建一個pass ,替換原有的數學函數調用帶有mask的svml函數。

 98615   vect__ifc__2106.1217_795 = VEC_COND_EXPR <mask__1612.1193_854, vect__1541.1206_870, { 0.0, 0.0, 0.0, 0.0 }>; 

設計方案:找到一個VEC_COND_EXPR,在同一個基本塊中,根據參數中的分支運算的結果,順著運算的關系一步步往上找(SSA_NAME_DEF_STMT),進行深度優先遍歷,直到找到了需要進行mask的數學函數。VEC_COND_EXPR中的參數mask就是數學函數需要進行mask的值。將數學函數和mask一起生成帶有mask的數學函數的IR,替換掉原來的不帶mask的。

?

由于次優化的性能和循環分塊重疊,因此不需要加入。

5.2 與oneapi性能差距的探索:

image-2024-8-30_17-6-5.png

對分支條件進行兩次判斷,一次判斷全為false,則不進入分支里面的運算。一次判斷全為true,如果正確,則只需要進入該分支的計算,其他分支不需要進入。相比于上述方案還省了分支條件全為true的時候的其他分支條件的運算。

由于涉及到的控制流和bb塊的修改較多,且不好驗證性能,暫且不做。

最終結果:性能在544 上提升7%。

544baseoptimize
32 copies100107

targetm.vectorize.empty_mask_is_expensive

或者看ifcvt IR 里面有沒有temp_value,loop vect里面有沒有combined_mask

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/76006.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/76006.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/76006.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LeetCode.3396.使數組元素互不相同所需的最少操作次數

3396. 使數組元素互不相同所需的最少操作次數 給你一個整數數組 nums&#xff0c;你需要確保數組中的元素 互不相同 。為此&#xff0c;你可以執行以下操作任意次&#xff1a; 從數組的開頭移除 3 個元素。如果數組中元素少于 3 個&#xff0c;則移除所有剩余元素。 注意&…

【已完結STM32】--自學江協科技筆記匯總

以下學習筆記代碼均來自b站江協科技視頻 筆記匯總完結 文章筆記對應江科大視頻新建工程【2-2】新建工程江科大STM32-GPIO輸出 點亮LED&#xff0c;LED閃爍&#xff0c;LED流水燈&#xff0c;蜂鳴器&#xff08;學習筆記&#xff09;_unit32-t rcc-apb2periph-CSDN博客 【3-1】…

QML Loader:加載組件與狀態監控

目錄 引言相關閱讀工程結構示例一&#xff1a;從文件加載組件 (LoaderFile.qml)代碼實現被加載的組件&#xff1a;MyComponent.qml代碼解析運行效果 示例二&#xff1a;直接加載Component對象 (LoaderComponent.qml)代碼實現代碼解析運行效果 示例三&#xff1a;監控加載狀態 (…

K8S核心技術點

Pod&#xff0c;Service和Deployment的關系 Pod&#xff1a;Kubernetes 中最小的部署單元&#xff0c;用于運行容器化應用。 Service&#xff1a;提供服務發現和負載均衡&#xff0c;為 Pod 提供穩定的網絡端點&#xff0c;ClusterIP&#xff0c;NodePort&#xff0c;LoadBala…

Spring 核心注解深度解析:@Autowired、@Repository 與它們的協作關系

引言 在 Spring 框架中&#xff0c;?依賴注入&#xff08;DI&#xff09;?? 是實現松耦合架構的核心機制。Autowired 和 Repository 作為兩個高頻使用的注解&#xff0c;分別承擔著 ?依賴裝配? 和 ?數據訪問層標識? 的關鍵職責。本文將深入探討它們的功能特性、協作模式…

[Linux]從零開始的ARM Linux交叉編譯與.so文件鏈接教程

一、前言 最近在項目需要將C版本的opencv集成到原本的代碼中從而進行一些簡單的圖像處理。但是在這其中遇到了一些問題&#xff0c;首先就是原本的opencv我們需要在x86的架構上進行編譯然后將其集成到我們的項目中&#xff0c;這里我們到底應該將opencv編譯為x86架構的還是編譯…

svelte+vite+ts+melt-ui從0到1完整框架搭建

框架太“重”了&#xff1a;通常一個小型項目只由少數幾個簡單頁面構成&#xff0c;如果使用 Vue 或者 React 這些框架來研發的話&#xff0c;有點“大材小用”了。構建的產物中包含了不少框架運行時代碼(虛擬 DOM、響應式、狀態管理等)&#xff0c;這些代碼對于小型項目而言是…

無法看到新安裝的 JDK 17

在 Linux 系統中使用 update-alternatives --config java 無法看到新安裝的 JDK 17&#xff0c;可能是由于 JDK 未正確注冊到系統備選列表中。 一、原因分析 JDK 未注冊到 update-alternatives update-alternatives 工具需要手動注冊 JDK 路徑后才能識別新版本。如果僅安裝 JDK…

鼎訊信通 便攜式雷達信號干擾模擬器:打造實戰化電磁環境的新利器

在現代戰爭中&#xff0c;電磁環境的復雜性直接影響著雷達裝備的性能和作戰效果。面對敵方日益精進的電子戰手段&#xff0c;如何提升雷達設備的抗干擾能力&#xff0c;確保其在實戰環境中的穩定性和可靠性&#xff0c;已成為各國軍隊和科研機構的重要課題。 為此&#xff0c;…

【AI提示詞】決策專家

提示說明 決策專家可以幫助你進行科學決策&#xff0c;盡可能避免錯誤&#xff0c;提升決策成功的概率。 提示詞 # Role : 決策專家決策&#xff0c;是面對不容易判斷優劣的幾個選項&#xff0c;做出正確的選擇。說白了&#xff0c;決策就是拿個主意。決策專家是基于科學決策…

力扣Hot100題,刷題

力扣HOT100 - 1. 兩數之和 解題思路&#xff1a; 解法一&#xff1a;暴力 class Solution {public int[] twoSum(int[] nums, int target) {int n nums.length;for (int i 0; i < n; i)for (int j i 1; j < n; j) {if (target nums[i] nums[j])return new int[]…

uni-app ucharts自定義換行tooltips

實現效果&#xff1a; 第一步&#xff1a;在uni_modules文件夾下找到config-ucharts.js和u-charts.js文件 第二步&#xff1a;在config-ucharts.js文件中配置換行格式 // 換行格式"wrapTooltip":function(item, category, index, opts){return item.name&#xff1a;…

國標GB28181視頻平臺EasyCVR順應智慧農業自動化趨勢,打造大棚實時視頻監控防線

一、方案背景 近年來&#xff0c;溫室大棚種植技術憑借其顯著的優勢&#xff0c;在提升農作物產量和質量、豐富農產品供應方面發揮了重要的作用&#xff0c;極大改善了人們的生活水平&#xff0c;得到了廣泛的推廣和應用。大棚內的溫度、濕度、光照度和二氧化碳濃度等環境因素…

InternVideo2.5:Empowering Video MLLMs with Long and Rich Context Modeling

一、TL&#xff1b;DR InternVideo2.5通過LRC建模來提升MLLM的性能。層次化token壓縮和任務偏好優化&#xff08;mask時空 head&#xff09;整合到一個框架中&#xff0c;并通過自適應層次化token壓縮來開發緊湊的時空表征MVBench/Perception Test/EgoSchema/MLVU數據benchmar…

【時時三省】(C語言基礎)條件運算符和條件表達式

山不在高&#xff0c;有仙則名。水不在深&#xff0c;有龍則靈。 ----CSDN 時時三省 有一種if語句&#xff0c;當被判別的表達式的值為“真”或“假”時&#xff0c;都執行一個賦值語句且向一個變量賦值。 如&#xff1a; if ( a > b ) max a&#xff1b; else max …

KWDB創作者計劃—邊緣計算:從概念到落地的技術解讀

引言 隨著物聯網&#xff08;IoT&#xff09;和人工智能&#xff08;AI&#xff09;的快速發展&#xff0c;數據量呈爆炸式增長&#xff0c;傳統的云計算架構逐漸暴露出延遲高、帶寬占用大等問題。邊緣計算作為一種新興的分布式計算范式&#xff0c;正在改變數據處理的方式。本…

藍橋杯基礎算法-遞歸

代碼簡潔&#xff0c;但涉及到的運算&#xff0c;會隨著遞歸層數的增加成指數級增長 路分析&#xff1a;第20行20列位于45度這條線上 這條線上的數字是1 5 13 25 41...兩數之差:4 8 12 16 --->每一個都是在前面的基礎上4&#xff0c;可以用遞歸或者循環 public class dem…

通過學習opencv圖像庫編程借助第三方庫函數完成一個綜合程序設計

通過學習opencv圖像庫編程借助第三方庫函數完成一個綜合程序設計 1) 編譯命令解釋&#xff1a; 編譯命令&#xff1a; gcc test1.cpp -o test1 pkg-config --cflags --libs opencv這條命令包含了以下部分&#xff1a; gcc test1.cpp -o test1: gcc 是 GNU 編譯器集合&#…

第十四屆藍橋杯大賽軟件賽國賽C/C++研究生組

研究生C國賽軟件大賽 題一&#xff1a;混乘數字題二&#xff1a;釘板上的正方形題三&#xff1a;整數變換題四&#xff1a;躲炮彈題五&#xff1a;最大區間 題一&#xff1a;混乘數字 有一點像哈希表&#xff1a; 首先定義兩個數組&#xff0c;拆分ab和n 然后令n a*b 查看兩個…

系統與網絡安全------網絡通信原理(2)

資料整理于網絡資料、書本資料、AI&#xff0c;僅供個人學習參考。 物理層解析 物理層概述 物理層是TCP/IP模型的最底層物理層數據傳輸提供穩定的物理連接 物理層功能 定義設備的物理連接的標準和特性&#xff0c;比如接口形狀&#xff0c;大小定義電氣特性&#xff0c;高低…