Уведомления

Группа в Telegram: @pythonsu

#1 Окт. 12, 2016 03:42:40

marina932
Зарегистрирован: 2016-02-22
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

numpy оптимизация

 list(zip(*np.unique(text, return_counts=True)))
Можно ли как-то оптимизировать этот код (может быть распараллелить?), а то на массиве из 100 000 000 программа на этом месте застревает на 10 секунд, если возможно хотелось бы быстрее.

Отредактировано marina932 (Окт. 12, 2016 04:31:16)

Офлайн

#2 Окт. 12, 2016 07:55:11

noob_saibot
Зарегистрирован: 2013-09-11
Сообщения: 495
Репутация: +  20  -
Профиль   Отправить e-mail  

numpy оптимизация

У вас на входе numpy массив? или вы так назвали список?
Вам там точно list нужен?
Может zip на dstack поменять?

PS. Нужно больше кода.

Отредактировано noob_saibot (Окт. 12, 2016 07:55:37)

Офлайн

#3 Окт. 12, 2016 08:24:17

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

numpy оптимизация

noob_saibot
PS. Нужно больше кода.
И данных :)
marina932 проведите дальше декомпозицию - определите доли в этих 10 секундах list(zip(*)) и unique.

Вопрос возникает потому что непонятно что такое text.

Оптимизация в вашем случае если и возможна, то только изменением входных и выходных данных надо менять объемлющий алгоритм.
вот вам код на подумать
 #include <iostream>
#include <iomanip>
using namespace std;
const int N=100000000;
const int M=256;
static unsigned char arr[N];
int main()
{
    int count[M]={0};
    int i;
    for(i=0;i<N;++i){arr[i]=i;}
    for(i=0;i<N;++i){++count[arr[i]];}
    for(i=0;i<M;++i)
    {
        cout<<count[i]<<endl;
    }
    cout<<"done"<<endl;
    return 0;
}

он на слабеньком ноутбуке выполнется меньше секунды.



Отредактировано doza_and (Окт. 12, 2016 08:44:42)

Офлайн

#4 Окт. 12, 2016 12:09:05

marina932
Зарегистрирован: 2016-02-22
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

numpy оптимизация

alphabet состоит из 10 символов, size = 100 000 000

 text = np.random.choice(list(alphabet.keys()), p=list(alphabet.values()), size=length)

noob_saibot
Может zip на dstack поменять?
Мне кажется нет смысла, потому на выходе у меня всего 10 символов будет + для каждого будет указана частота появления в коде.

Отредактировано marina932 (Окт. 12, 2016 12:09:38)

Офлайн

#5 Окт. 12, 2016 13:49:46

marina932
Зарегистрирован: 2016-02-22
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

numpy оптимизация

doza_and
Си это конечно хорошо и быстро, но хотел обойтись python, на нем все таки пишу.

Офлайн

#6 Окт. 12, 2016 13:58:43

noob_saibot
Зарегистрирован: 2013-09-11
Сообщения: 495
Репутация: +  20  -
Профиль   Отправить e-mail  

numpy оптимизация

marina932
doza_andСи это конечно хорошо и быстро, но хотел обойтись python, на нем все таки пишу.
Вы же в курсе почему doza_and написал на си?

Офлайн

#7 Окт. 12, 2016 14:26:44

marina932
Зарегистрирован: 2016-02-22
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

numpy оптимизация

noob_saibot
Да знаю, что можно расширения на си писать, но все же не хотелось бы это делать. Если без этого ни как вообще, то думаю лучше будет cython использовать.

Офлайн

#8 Окт. 12, 2016 14:53:52

marina932
Зарегистрирован: 2016-02-22
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

numpy оптимизация

В общем частично решила проблему тем, что теперь считаю частоту появления символов не в итоговом массиве, а у каждой части общего массива, который генерится в отдельном потоке.

Отредактировано marina932 (Окт. 12, 2016 18:41:36)

Офлайн

#9 Ноя. 7, 2016 04:14:16

izekia
От:
Зарегистрирован: 2008-07-19
Сообщения: 317
Репутация: +  12  -
Профиль   Отправить e-mail  

numpy оптимизация

У меня машина медленная, поэтому результаты по абсолютному времени могут различаться:

 import random
import numpy as np
def create_text(length):
    alphabet = {str(i-1): np.float64(i / 55.0) for i in range(1, 11)}
    return np.random.choice(list(alphabet.keys()), p=list(alphabet.values()), size=length)
text = create_text(100000000)
text, len(text)
(array(,
dtype='<U1'), 100000000)
 def f_prev(text):
    l1 = np.unique(text, return_counts=True)
    l2 = zip(*l1)
    l3 = {code: count for code, count in l2}
    return l3
 def f_view(text):
    l1 = np.unique(text.view(np.int), return_counts=True)
    l2 = zip(*l1)
    l3 = {chr(code): count for code, count in l2}
    return l3
 f_prev(text)
{'0': 1820740,
‘1’: 3636051,
‘2’: 5458589,
‘3’: 7271355,
‘4’: 9086383,
‘5’: 10906851,
‘6’: 12728655,
‘7’: 14542164,
‘8’: 16360778,
‘9’: 18188434}
 f_prev(text) == f_view(text)
True
 %%timeit -n 5
f_prev(text)
5 loops, best of 3: 21.3 s per loop
 %%timeit -n 5
f_view(text)
5 loops, best of 3: 8.16 s per loop

PS: чуть позже может через сифон другой вариант попробую, но нет уверенности что будет много быстрее



Офлайн

#10 Ноя. 8, 2016 04:22:52

izekia
От:
Зарегистрирован: 2008-07-19
Сообщения: 317
Репутация: +  12  -
Профиль   Отправить e-mail  

numpy оптимизация

странно, а я думал, что все методы numpy дико оптимизированы:

 %%cython -a 
#cython: boundscheck=False
import numpy as np
cimport numpy as np
cpdef trivial1_cyth1(text):
    cdef int[:] text_int_view = text.view(np.int)
    cdef int[:] c = np.zeros(256, dtype=np.int)
    cdef int l = len(text_int_view )
    cdef int i
    for i in range(l):
        c[text_int_view [i]] += 1
    return {chr(i): c[i] for i in range(len(c)) if c[i] > 0}

 text, len(text)
(array(,
dtype='<U1'), 100000000)
 %%timeit
trivial1_cyth1(text)
1 loop, best of 3: 375 ms per loop
 def f_prev(text):
    l1 = np.unique(text, return_counts=True)
    l2 = zip(*l1)
    l3 = {code: count for code, count in l2}
    return l3
 %%timeit -n 5
f_prev(text)
5 loops, best of 3: 24.3 s per loop
 res = trivial1_cyth1(text)
res_prev = f_prev(text)
res == res_prev
True



Отредактировано izekia (Ноя. 8, 2016 04:26:59)

Прикреплённый файлы:
attachment alph.JPG (46,1 KБ)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version