मैं ईएम-जीएमएम का एक विशेष मामला लागू कर रहा हूं।

X आकार का डेटा मैट्रिक्स है [1000000, 900] और एक numpy mmap ऑब्जेक्ट है
क्यू आकार का एक सटीक मैट्रिक्स है [९००, ९००] और एक ndarray . है

मैं एक ही डेटा मैट्रिक्स (एक्स) का उपयोग करके, 40 कोर पर एक साथ 200 क्यू मैट्रिस पर जाने के लिए मल्टीप्रोसेसिंग लाइब्रेरी का भी उपयोग कर रहा हूं।

यह [1mil, 196], [1mil, 400],
. जैसे छोटे आयामों पर काम करता है लेकिन जब मैं प्रक्रियाओं के किसी बिंदु पर [1mil, 900] चलाने की कोशिश करता हूं तो अपवाद फेंकता है:

OSError: [Errno 12] मेमोरी आवंटित नहीं कर सकता

मुझे लगता है कि यह मुद्दा मेरे पास 2 बड़ी गणनाओं के कारण है, जो शायद बड़े मैट्रिस आवंटित करते हैं।

ई-चरण के भाग के रूप में मुझे गणना करने की आवश्यकता है:
np.sum(X.dot(Q) * X, axis=1)

एम-स्टेप के भाग के रूप में मुझे गणना करने की आवश्यकता है (डब्ल्यू एक [१मिल, १] वज़न वेक्टर है):
(X.T * W).dot(X)

भविष्य में मुझे इस EM-GMM को और भी बड़े आकार (आकार [2mil, 2500] और यहां तक ​​कि [2mil, 10k]) के डेटा पर चलाना होगा
मैं उन गणनाओं को अधिक मेमोरी कुशल बनाने के लिए क्या कर सकता हूं?

संपादित करें:

मैंने देखा है कि कार्यकर्ता आरंभीकरण अचार का उपयोग करता है, इसलिए एक्स-मैट्रिक्स को ndarray में बदल दिया जाता है और कार्यकर्ता इसे साझा नहीं करते हैं (जिसका अर्थ है कि एक्स-मैट्रिक्स सभी श्रमिकों के लिए डुप्लिकेट किया गया है और मेरी रैम भरता है)

मेरे पास इसे हल करने के बारे में एक विचार है, और अगर यह ठीक हो जाता है तो मैं इसे अपडेट कर दूंगा।
लेकिन अगर किसी के पास इससे निपटने का अच्छा विचार है तो मैं आभारी रहूंगा।

0
Shahaf Finder 9 अक्टूबर 2018, 10:52

1 उत्तर

सबसे बढ़िया उत्तर

यह पता चला कि 2 असंबंधित मुद्दे थे जो रैम के अति प्रयोग का कारण बने।

सबसे पहले, मल्टीप्रोसेसिंग श्रमिकों के लिए चुने जाने पर मेममैप ऑब्जेक्ट को डिस्क से पूरी तरह से पढ़ा गया था।
डेटा के इस दोहराव ने प्रत्येक कार्यकर्ता के लिए 6.7GB अतिरिक्त RAM आवंटित की।
इसे हल करने के लिए, मैंने एक साझा RawArray बनाया है और इसमें डेटा लोड किया है, और प्रत्येक कार्यकर्ता पर मैंने np.frombuffer का उपयोग किया है।

दूसरा, दोनों X.dot(Q) और (X.T * W) के परिणामस्वरूप एक और एक्स-आकार का मैट्रिक्स आवंटित किया गया, जो एक और 6.7GB RAM है
मैंने इस धागे से उत्तर की विविधता बनाई: https://stackoverflow.com/a/21096605/5572523
चूंकि मेरा मैट्रिक्स पतला-लंबा है, इसलिए मैं पंक्तियों में कटा हुआ हूं:

def _block_slices(dim_size, block_size):
    count = 0
    while True:
        yield slice(count, count + block_size, 1)
        count += block_size
        if count >= dim_size:
            raise StopIteration

और अब मैं डेटा के बैचों पर पुनरावृति कर सकता हूं (वजन = 0 से निपटने के दौरान थोड़ा अतिरिक्त स्पीडअप भी जोड़ा गया)

मैंने max_elements = 2 ** 27 सेट किया है, क्योंकि मैं फ्लोट64 का उपयोग कर रहा हूं, इसलिए इसका परिणाम 1GB मैट्रिक्स में होता है (यदि मैं गलत नहीं हूं)।

तो (X.T * W).dot(X) बदल गया:

def weighted_outer_prod(X, W):
    n, d = X.shape

    max_rows = max(1, int(max_elements / d))
    sigma = np.zeros([d, d])
    for mm in _block_slices(n, max_rows):
        sigma += batch_weighted_outer_prod(X[mm, :], W[mm])
    return sigma

def batch_weighted_outer_prod(batch, W):
    nz = W > 0
    buff = np.empty(batch[nz].shape)
    np.multiply(batch[nz], W[nz, np.newaxis], out=buff)
    sigma = buff.T.dot(batch[nz])
    del(buff)
    return sigma

और np.sum(X.dot(Q) * X, axis=1) में बदल गया: (फ़ंक्शन नाम पर ध्यान न दें)

def calc_l_k(X, Q):
    max_rows = max(1, int(max_elements / d))
    l_k = np.empty(n)
    for mm in _block_slices(n, max_rows):
        l_k[mm] = batch_l_k(X[mm, :], Q)

    return l_k


def batch_l_k(batch, Q):
    buff = np.empty(batch.shape)
    np.dot(batch, Q, out=buff)
    np.multiply(buff, batch, out=buff)
    l_k = -0.5 * np.sum(buff, axis=1)
    del(buff)
    return l_k

अब यह X आकार [1mil, 900] के साथ चलता है, और मुझे आशा है कि यह अभी भी उच्च आयामों के साथ काम करेगा।

1
Shahaf Finder 9 अक्टूबर 2018, 22:20