主頁 > 軟體設計 > 在Python中使用嵌套回圈重寫MATLAB代碼并快速執行

在Python中使用嵌套回圈重寫MATLAB代碼并快速執行

2022-04-06 23:41:09 軟體設計

這是一個嵌套回圈,其中內部索引依賴于外部索引,具有以下引數:

f = rand(1,70299)
nech=24*30*24
N=length(f);
xh=(1:nech)/24;

在 MATLAB 中:

sf2(1:nech)=0.;
sf2vel(1:nech)=0.;
count(1:nech)=0.;

for i=1:nech
    for j=1:N-i-1
        sf2(i)=sf2(i) (f(j i)-f(j))^2;
        count(i)=count(i) 1; 
    end
    sf2(i)=sf2(i)/count(i);
end

在 Python 中:

def structFunPython(f,N,nech):
    sf2 = np.zeros(N)
    count = np.zeros(N)
    for i in range(nech):
        indN = np.arange(1,N-i-1)
        for j in indN:
            sf2[i]  = np.power((f[i j]-f[j]),2)
            count[i]  = 1
        sf2[i] = sf2[i]/count[i]
    return sf2

使用 cython:

import cython
cimport numpy as np
import numpy as np
def structFun(np.ndarray f,N,nech):
    cdef np.ndarray sf2 = np.zeros(N), count = np.zeros(N),
    for i in range(nech):
        indN = np.arange(1,N-i-1)
        for j in indN:
            sf2[i]  = np.power((f[i j]-f[j]),2)
            count[i]  = 1
        sf2[i] = sf2[i]/count[i]
    return sf2

Executions times:

Matlab: 7.8377 sec
Python: 3651.35 sec
Cython: 3336.21 sec

I have a hard time believing Python and Cython (especially Cython) are that slow for the same computation, so I think I must have made an error in my Python/Cython loops, but I can't see where.

uj5u.com熱心網友回復:

免責宣告:正如@norok2 在評論中指出的那樣,N*(N-1)/2由于使用pdist. 對您而言N = 70299,這意味著陣列中有大約 18.5 GB 的雙精度。其他索引陣列將具有相似的大小。因此,除非您的某些用例較小N,否則此答案中的矢量化方法僅在您有大量記憶體時才可行。


正如其他人所指出的,僅將代碼從一種語言翻譯成另一種語言不會導致兩種語言的最佳代碼。并且單獨使用 Cython 并不能保證加速,就像單獨使用 NumPy 不能保證加速一樣。

norok2 的回答很好地向您展示了如何使用numba或類似的東西來編譯您的數字代碼。這可以為您提供與 MATLAB 中的性能非常相似的東西,因為 MATLAB 有自己的即時 (JIT) 編譯器。還有回旋余地來優化您的編譯代碼,因為多個實作最終可能會產生截然不同的性能。

無論如何,我想說的是,您還可以通過使用 NumPy 和 SciPy 中的高級功能來加速您的代碼。特別是,您想要計算一組 1d 點之間的成對平方距離。這就是scipy.spatial.distance.pdist可以為您做的(使用'sqeuclidean'平方歐幾里得范數)。好處是它只計算每個成對距離一次(這對 CPU 和記憶體性能很有幫助),但缺點是選擇你想要總結的貢獻有點麻煩。

無論如何,這是與您的 Python 實作相對應的代碼(帶有內部回圈使用np.arange(1, N-i)而不是的修復np.arange(1, N-i-1)):

from scipy.spatial.distance import pdist

def pdisty(f, nech):
    offset = f.size - nech
    res = np.zeros_like(f, shape=nech)
    dists = pdist(f[:, None], metric='sqeuclidean')
    counts = np.arange(offset, f.size)[::-1]
    inds = np.repeat(np.arange(res.size), counts)
    np.add.at(res, inds, dists[:inds.size])
    res /= counts
    return res

這里發生的是

  1. 我們計算每對唯一陣列值的成對距離并將其存盤到dists
  2. 我們計算每個點所涉及的對數(這是我們最后必須標準化的),將其存盤到counts
  3. 找出dists它對應的每個值的一維索引(這是困難的部分),將其存盤在inds
  4. 用于np.add.at累積對適當輸出指數的每個貢獻
  5. 用計數標準化。

以下是一些時間N = 1000norok2 的答案func2()中的相應函式在哪里

>>> %timeit structFunPython(f, f.size - 1)
... %timeit func2(f, f.size - 1)
... %timeit pdisty(f, f.size - 1)
1.48 s ± 89.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
274 ms ± 2.71 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
36.7 ms ± 1.21 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

上述解決方案要快得多,但當然它仍然比完全編譯的解決方案慢。如果您對附加依賴項或在系統上安裝 llvm 有疑問,這可能是一個合理的折衷方案。底線是代碼應該適應你試圖優化它的語言。


為了完整起見,這里是我用于比較的實作(我稍微更改了簽名,因為N可以從輸入陣列計算,并且我修復了一些 fencepost 錯誤):

def structFunPython(f, nech):
    """Very slightly modified from the question"""
    N = f.size
    sf2 = np.zeros(nech)
    count = np.zeros(nech)
    for i in range(nech):
        indN = np.arange(1,N-i)
        for j in indN:
            sf2[i]  = np.power((f[i j]-f[i]),2)
            count[i]  = 1
        sf2[i] = sf2[i]/count[i]
    return sf2


def func2(f_arr, nech):
    """Very slightly modified from norok2's answer

    See https://stackoverflow.com/a/71704834/5067311

    """
    n = f_arr.size
    sf2 = np.zeros(nech)
    for i in range(nech):
        for j in range(1, n - i):
            sf2[i]  = (f_arr[i   j] - f_arr[i]) ** 2
        sf2[i] /= (n - i - 1)
    return sf2

通過這些定義,所有三個函式在機器精度內給出相同的結果:

rng = np.random.default_rng()
N = 1000
nech = N - 2
f = rng.random(1000)
assert np.allclose(structFunPython(f, nech), func2(f, nech))
assert np.allclose(structFunPython(f, nech), pdisty(f, nech))

uj5u.com熱心網友回復:

我將 MATLAB 代碼重寫為等效 Python 代碼的方式可能是(注意在 MATLAB 中從 1 開始,在 Python 中從 0 開始的索引......因為我不知道在沒有背景關系的情況下應該如何調整它,所以我采用了最簡單的方法):

import numpy as np


def func(f_arr, nech, n):
    sf2 = np.zeros(nech)
    count = np.zeros(nech)
    for i in range(nech):
        for j in range(n - i):
            sf2[i]  = (f_arr[i   j] - f_arr[i]) ** 2
            count[i]  = 1
        sf2[i] /= count[i]
    return sf2

請注意,這count[i] = 1是無用的,因為 的最終值count[i]是預先知道的,實際上整體count是無用的,例如:

import numpy as np


def func2(f_arr, nech, n):
    sf2 = np.zeros(nech)
    for i in range(nech):
        for j in range(n - i):
            sf2[i]  = (f_arr[i   j] - f_arr[i]) ** 2
        sf2[i] /= (n - i)
    return sf2

加速

這是 Numba 加速的手動案例。這就像添加/使用 Numba@njit裝飾器一樣簡單:

import numba as nb


func_nb = nb.njit(func)
func2_nb = nb.njit(func2)

現在,func執行相同的計算:func_nbfunc2func2_nb

nech = n = 6
f_arr = np.arange(n)
print(func(f_arr, nech, n))
# [9.16666667 6.         3.5        1.66666667 0.5        0.        ]
print(func_nb(f_arr, nech, n))
# [9.16666667 6.         3.5        1.66666667 0.5        0.        ]
print(func2(f_arr, nech, n))
# [9.16666667 6.         3.5        1.66666667 0.5        0.        ]
print(func2_nb(f_arr, nech, n))
# [9.16666667 6.         3.5        1.66666667 0.5        0.        ]

如果你真的需要堅持使用 Cython,這里有一個基于func2

%%cython -c-O3 -c-march=native -a
#cython: language_level=3, boundscheck=False, wraparound=False, initializedcheck=False, cdivision=True, infer_types=True


import numpy as np
import cython as cy


cpdef func2_cy(f_arr, nech, n):
    sf2 = np.zeros(nech)
    _func2_cy(f_arr.astype(np.float_), sf2, nech, n)
    return sf2


cdef _func2_cy(double[:] f_arr, double[:] sf2, cy.int nech, cy.int n):
    for i in range(nech):
        for j in range(1, n - i):
            sf2[i] = sf2[i]   (f_arr[i   j] - f_arr[i]) ** 2
        sf2[i] = sf2[i] / (n - i)

與 Numba 相比,這寫起來要復雜得多,但實作了相似的性能。訣竅是擁有一個_func2_cy與 Python 幾乎沒有互動的函式(閱讀:它以 C 速度運行)。

結果再次與以下相同func2

nech = n = 6
f_arr = np.arange(n)
print(func2_cy(f_arr, nech, n))
# [9.16666667 6.         3.5        1.66666667 0.5        0.        ]

計時

With some little toy benchmarking we get a feeling of the speed-ups, including a comparable function written as you did, and the vectorized solution proposed in Andras Deak's very fine answer (but fixing the indices to match the above):

def func_OP(f, nech, n):
    sf2 = np.zeros(n)
    count = np.zeros(n)
    for i in range(nech):
        indN = np.arange(n - i)  # <-- indexing fixed
        for j in indN:
            sf2[i]  = np.power((f[i j]-f[i]),2)
            count[i]  = 1
        sf2[i] = sf2[i] / count[i]
    return sf2


func_OP_nb = nb.njit(func_OP)
def func_pdisty(f, nech, n):
    res = np.zeros(nech)
    dists = scipy.spatial.distance.pdist(f[:, None], metric='sqeuclidean')
    counts = np.arange(n - 1, n - nech - 1, -1)
    inds = np.repeat(np.arange(res.size), counts)
    np.add.at(res, inds, dists[:inds.size])
    res /= (counts   1)
    return res
nech = n = 6
f_arr = np.arange(n)
print(func_OP(f_arr, nech, n))
# [9.16666667 6.         3.5        1.66666667 0.5        0.        ]
print(func_pdisty(f_arr, nech, n))
# [9.16666667 6.         3.5        1.66666667 0.5        0.        ]
nech = n = 1000
f_arr = np.arange(n)
%timeit func_OP(f_arr, nech, n)
# 1 loop, best of 5: 1.5 s per loop
%timeit func(f_arr, nech, n)
# 1 loop, best of 5: 567 ms per loop
%timeit func2(f_arr, nech, n)
# 1 loop, best of 5: 352 ms per loop
%timeit func_OP_nb(f_arr, nech, n)
# 1000 loops, best of 5: 1.87 ms per loop
%timeit func_nb(f_arr, nech, n)
# 1000 loops, best of 5: 1.7 ms per loop
%timeit func2_nb(f_arr, nech, n)
# 1000 loops, best of 5: 768 μs per loop
%timeit func_pdisty(f_arr, nech, n)
# 10 loops, best of 5: 44.5 ms per loop
%timeit func2_cy(f_arr, nech, n)
# 1000 loops, best of 5: 1 ms per loop
nech = n = 2000
f_arr = np.arange(n)
%timeit func_OP(f_arr, nech, n)
# 1 loop, best of 5: 6.01 s per loop
%timeit func(f_arr, nech, n)
# 1 loop, best of 5: 2.3 s per loop
%timeit func2(f_arr, nech, n)
# 1 loop, best of 5: 1.42 s per loop
%timeit func_OP_nb(f_arr, nech, n)
# 100 loops, best of 5: 7.31 ms per loop
%timeit func_nb(f_arr, nech, n)
# 100 loops, best of 5: 6.82 ms per loop
%timeit func2_nb(f_arr, nech, n)
# 100 loops, best of 5: 3.05 ms per loop
%timeit func_pdisty(f_arr, nech, n)
# 1 loop, best of 5: 344 ms per loop
%timeit func2_cy(f_arr, nech, n)
# 100 loops, best of 5: 3.95 ms per loop
nech = n = 4000
f_arr = np.arange(n)
%timeit func_OP(f_arr, nech, n)
# 1 loop, best of 5: 24.3 s per loop
%timeit func(f_arr, nech, n)
# 1 loop, best of 5: 9.27 s per loop
%timeit func2(f_arr, nech, n)
# 1 loop, best of 5: 5.71 s per loop
%timeit func_OP_nb(f_arr, nech, n)
# 10 loops, best of 5: 29 ms per loop
%timeit func_nb(f_arr, nech, n)
# 10 loops, best of 5: 27.3 ms per loop
%timeit func2_nb(f_arr, nech, n)
# 100 loops, best of 5: 12.2 ms per loop
%timeit func_pdisty(f_arr, nech, n)
# 1 loop, best of 5: 706 ms per loop
%timeit func2_cy(f_arr, nech, n)
# 100 loops, best of 5: 15.9 ms per loop

...and with the input sizes you provided:

nech = 24 * 30 * 24
n = 70299
f_arr = np.random.random(n)
%timeit -n1 -r1 func_OP(f_arr, nech, n)
# 1 loop, best of 1: 1h 4min 50s per loop
%timeit -n1 -r1 func(f_arr, nech, n)
# 1 loop, best of 1: 21min 14s per loop
%timeit -n1 -r1 func2(f_arr, nech, n)  # only one run / loop
# 1 loop, best of 1: 13min 9s per loop
%timeit func_OP_nb(f_arr, nech, n)
# 1 loop, best of 5: 4.74 s per loop
%timeit func_nb(f_arr, nech, n)
# 1 loop, best of 5: 4 s per loop
%timeit func2_nb(f_arr, nech, n)
# 1 loop, best of 5: 1.62 s per loop
# %timeit func_pdisty(f_arr, nech, n)
# -- MEMORY ERROR --
%timeit func2_cy(f_arr, nech, n)
# 1 loop, best of 5: 2.2 s per loop

uj5u.com熱心網友回復:

您已經得到了一些很好的答案,它們提供了快速的 numpy 和 numba 實作。我想介紹一個體面的 Cython 實作以進行公平比較。

首先,讓我們在我的機器上計時 norok2 最快的 numba 實作:

In [3]: %timeit func2_nb(f_arr, n)
3.4 s ± 129 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  • 為了在 Cython 中獲得快速的記憶體訪問,向其提供有關輸入陣列的所有必要資訊至關重要。在您的情況下,f_arr是一個 C-contiguous np.ndarray,所以我們使用 C-contiguous memoryviewsdouble[::1]而不是普通的 memoryviews double[:]不同之處在于,索引 C 連續記憶體視圖減少為純 C 代碼f_arr[i],而后者減少為f_arr[i f_arr.strides[0]].

  • 接下來值得一提的是,Python 的冪運算子a**2將被 C 代碼替代pow(a,2),即我們稱之為pow-function。在緊密回圈中呼叫函式會產生不必要的開銷,即使在 C 中也是如此。在 C 中,我們只需撰寫a*a. 所以讓我們在 Cython 中做同樣的事情。

在代碼中:

%%cython -c=-O3 -c=-march=native
# for MSVC use: -c=/Ox -c=/arch:AVX2
#           or: -c=/Ox -c=/arch:AVX512 if your CPU supports AVX512 

import numpy as np
cimport numpy as np
cimport cython

@cython.boundscheck(False)
@cython.wraparound(False)
def func2_cy(double[::1] f_arr, int nech):
    cdef int n = f_arr.size
    cdef double[::1] sf2 = np.zeros(nech)
    cdef int i, j
    for i in range(nech):
        for j in range(n-i-2):
            sf2[i]  = (f_arr[i j 1]-f_arr[i])*(f_arr[i j 1]-f_arr[i])
        sf2[i] /= (n - i - 2)
    return np.asarray(sf2)

在我的機器上使用 macOS 上的 Apple Clang 13.1.6 編譯,這比前面提到的 numba 實作要慢:

In [5]: %timeit func2_cy(f_arr, n)
4.2 s ± 32 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

但是,應該知道 Cython 基本上只是一個Python 到 C的編譯器。這意味著,在我們洗掉所有 python 互動之后,我們可以嘗試使用 C 代碼時應用的相同性能技巧:傳遞優化標志-O3并啟用當前平臺上可用的所有 CPU 指令-march=native請注意,這也意味著良好的 Cython 代碼(即在緊密回圈中沒有 python 互動的代碼)的性能在很大程度上取決于您的 C 編譯器。根據我的經驗,由于 MSVC 糟糕的自動矢量化,numba 通常比 Windows 上的 Cython 快。在 macOS/Linux 和 gcc 或 clang 上,通常情況正好相反。

One of these well-known performance tricks is loop-unrolling in order to give the compiler hints to SIMD-vectorize the specific loop. Unrolling the innermost loop, the function looks like this:

%%cython -c=-O3 -c=-march=native
# for MSVC use: -c=/Ox -c=/arch:AVX2
#           or: -c=/Ox -c=/arch:AVX512 if your CPU supports AVX512 

#cython: cdivision=True

import numpy as np
cimport numpy as np
cimport cython

@cython.boundscheck(False)
@cython.wraparound(False)
def func3_cy(double[::1] f_arr, int nech):
    cdef int n = f_arr.size
    cdef double[::1] sf2 = np.zeros(nech)
    cdef double fi, fij, fij1, fij2, fij3
    cdef int i, j, ntmp
    for i in range(nech):
        # unroll the inner loop for better SIMD vectorization
        j = 1
        ntmp = (n-i-2) - ((n-i-2) % 4)
        # we use a while-loop since Cython doesn't support range(j, ntmp, 4)
        while j < ntmp:
            # unpack the values and hope the CPU keeps them in its register
            fi   = f_arr[i]
            fij  = f_arr[i j 1]
            fij1 = f_arr[i j 2]
            fij2 = f_arr[i j 3]
            fij3 = f_arr[i j 4]
            sf2[i]  = ((fij-fi)*(fij-fi)   (fij1-fi)*(fij1-fi)   (fij2-fi)*(fij2-fi)   (fij3-fi)*(fij3-fi))
            j  = 4
        for j in range(ntmp, n - i - 2):
            sf2[i]  = (f_arr[i j 1] - f_arr[i]) * (f_arr[i j 1] - f_arr[i])
        sf2[i] /= (n-i-2)
    return np.asarray(sf2)

On my machine, this is nearly two times faster than numba:

In [7]: %timeit func3_cy(f_arr, n)
1.7 s ± 54.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

To take it one step further, we can parallelize the outer loop with the help of prange which is just a thin wrapper around OpenMP:

%%cython -c=-O3 -c=-march=native -c=-fopenmp --link-args=-fopenmp
# for MSVC use: -c=/Ox -c=/openmp -c=/arch:AVX2
#           or: -c=/Ox -c=/openmp -c=/arch:AVX512 if your CPU supports AVX512 

#cython: cdivision=True

import numpy as np
cimport numpy as np
cimport cython
from cython.parallel cimport prange

@cython.boundscheck(False)
@cython.wraparound(False)
def func4_cy(double[::1] f_arr, int nech):
    cdef int n = f_arr.size
    cdef double[::1] sf2 = np.zeros(nech)
    cdef double fi, fij, fij1, fij2, fij3
    cdef int i, j, ntmp
    for i in prange(nech, nogil=True, schedule="static", chunksize=1):
        # unroll the inner loop for better SIMD vectorization
        j = 1
        ntmp = (n-i-2) - ((n-i-2) % 4)
        # we use a while-loop since Cython doesn't support range(j, ntmp, 4)
        while j < ntmp:
            # unpack the values and hope the CPU keeps them in its register
            fi   = f_arr[i]
            fij  = f_arr[i j 1]
            fij1 = f_arr[i j 2]
            fij2 = f_arr[i j 3]
            fij3 = f_arr[i j 4]
            sf2[i]  = ((fij-fi)*(fij-fi)   (fij1-fi)*(fij1-fi)   (fij2-fi)*(fij2-fi)   (fij3-fi)*(fij3-fi))
            j  = 4
        for j in range(ntmp, n - i - 2):
            sf2[i]  = (f_arr[i j 1] - f_arr[i]) * (f_arr[i j 1] - f_arr[i])
        sf2[i] /= (n-i-2)
    return np.asarray(sf2)

On my machine with 8 CPU Cores, this is by far the fastest implementation:

In [9]: %timeit func4_cy(f_arr, n)
329 ms ± 15.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

However, it's worth mentioning that Numba also supports thread parallelism, so I'd expect a similar performance with Numba.

uj5u.com熱心網友回復:

通過一些基本的 python/numpy 重寫,我可以加快你的代碼速度

def structFunPython4(f,N,nech):
    sf2 = np.zeros(N)
    #count = np.zeros(N)
    for i in range(nech):
        # indN = np.arange(1,N-i-1)
        sf2[i] = np.sum(np.power(f[i 1:N-1]-f[i],2))
        #for j in range(1,N-i-1):
        #    sf2[i]  = np.power((f[i j]-f[i]),2)
        #    #count[i]  = 1
        sf2[i] = sf2[i]/(N-i-2)
    return sf2

對于適度的樣本量:

In [53]: f = np.arange(100); N=f.shape[0]; nech=98

他們匹配:

In [54]: np.allclose(structFunPython(f,N,nech),structFunPython4(f,N,nech))
Out[54]: True

和時間:

In [55]: timeit structFunPython(f,N,nech)
34.4 ms ± 109 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [56]: timeit structFunPython4(f,N,nech)
2.22 ms ± 35.9 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

我首先替換for i in indN:for i in range(1,N-1-i):. 對陣列的迭代比對串列或 的迭代慢range

正如其他人指出的那樣,我們不需要迭代count.

但最大的變化是j用陣列切片代替迭代,對整個切片和陣列求和進行電源。

我還沒有看到i足夠的迭代來消除它。 f[i 1:N-1]slice 的長度不同,從nech低到 0。

MATLAB 做了很多 jit 編譯,所以你可以通過迭代來解決。早在 1990 年代,當我使用 MATLAB 時,它的形式會很糟糕——那些版本需要全矩陣計算才能獲得任何合理的速度。Python 級別的迭代很慢(解釋),并且在陣列上比在串列上慢。盡可能嘗試使用整體陣列方法。或用于numba編譯計算。

====

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/456633.html

標籤:python numpy matlab cython nested-loops

上一篇:JNA在Linux上使用64位libmx.so崩潰

下一篇:檢查矩陣是否是3d陣列元素的最快方法是什么?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more