Numpy очень медленно при выполнении цикла - PullRequest
1 голос
/ 09 ноября 2011

Я занимаюсь разработкой агентской модели рынка труда в python / numpy. Модель ориентирована на процесс подбора работников и фирм, которые характеризуются l-мерными битовыми последовательностями. Рабочие и фирмы с точно подобранными последовательностями битов сопоставляются друг с другом.

В этот момент модель работает правильно и выдает правильный вывод. Тем не менее, это очень медленно. Это займет около 77 секунд за 20 итераций. (Я использую модель на Macbook Pro с процессором i5 и 8 ГБ ОЗУ). Для сравнения, я изначально написал модель в R, где 20 итераций занимает примерно 0,5 секунды. Это кажется действительно странным, так как из всего, что я прочитал, python должен работать быстрее, чем R для циклов и других функций программирования.

Я потратил много времени, пытаясь оптимизировать код и изучая проблемы с numpy. Кроме того, я попытался запустить модель в Sage, но не заметил никакой разницы.

Я прилагаю ключевые сегменты кода ниже. Пожалуйста, дайте мне знать, если есть проблемы с кодом или есть другие проблемы с numpy, которые я мог пропустить.

Спасибо

Даниэль Шеер

Код:

from __future__ import division
from numpy import*
import numpy as np
import time
import math as math

NUM_WORKERS         = 1000
NUM_FIRMS           = 65
ITERATIONS          = 20
HIRING_THRESHOLD    = 0.4
INTERVIEW_THRESHOLD = 0.2
RANDOM_SEED         = 1
SKILLSET_LENGTH     = 50
CONS_RETURN         = 1
INC_RETURN          = 1
RETURN_COEFF        = 1.8
PRODUCTIVITY_FACTOR = 0.001

#"corr" function computes closeness between worker i and firm j
def corr(x,y):
    return 1-(np.sum(np.abs(x-y))/SKILLSET_LENGTH)

#"skill_evolve" function randomly changes a segment of the firm's skill demand bit string
def skill_evolve(start,end,start1,q,j,firms):
    random.seed(q*j)
    return around(random.uniform(0,1,(end-start1)))

#"production" function computes firm output
def production(prod):
    return (CONS_RETURN*prod)+math.pow(INC_RETURN*prod,RETURN_COEFF)

#"hire_unemp" function loops though unemployed workers and matches them with firms
def hire_unemp(j):
    for i in xrange(NUM_WORKERS):
        correlation = corr(workers[(applicants[i,0]-1),9:(9+SKILLSET_LENGTH+1)],firms[j,4:(4+SKILLSET_LENGTH+1)])
        if (workers[(applicants[i,0]-1),3] == 0 and correlation > HIRING_THRESHOLD and production(correlation*PRODUCTIVITY_FACTOR) >= (production((firms[j,2]+(correlation*PRODUCTIVITY_FACTOR))/(firms[j,1]+1)))):
            worker_row = (applicants[i,0]-1)
            workers[worker_row,3] = firms[j,0]
            workers[worker_row,4] = correlation
            workers[worker_row,5] = (workers[worker_row,4]+workers[worker_row,1])*PRODUCTIVITY_FACTOR
            firms[j,1] = firms[j,1]+1
            firms[j,2] = firms[j,2]+workers[worker_row,5]
            firms[j,3] = production(firms[j,2])
            workers[worker_row,7] = firms[j,3]/firms[j,1]
            #print "iteration",q,"loop unemp","worker",workers[worker_row,0]
            break

#"hire_unemp" function loops though employed workers and matches them with firms 
def hire_emp(j):
    for i in xrange(NUM_WORKERS):
        correlation = corr(workers[(applicants[i,0]-1),9:(9+SKILLSET_LENGTH+1)],firms[j,4:(4+SKILLSET_LENGTH+1)])
        if (workers[(applicants[i,0]-1),3] > 0 and correlation > HIRING_THRESHOLD and (production((firms[j,2]+(correlation*PRODUCTIVITY_FACTOR))/(firms[j,1]+1) > workers[(applicants[i,0]-1),7]))):
            worker_row = (applicants[i,0]-1)
            otherfirm_row = (workers[worker_row,3]-1)
            #print q,firms[otherfirm_row,0],firms[otherfirm_row,1],"before"
            firms[otherfirm_row,1] = firms[otherfirm_row,1]-1
            #print q,firms[otherfirm_row,0],firms[otherfirm_row,1],"after"
            firms[otherfirm_row,2] = array([max(array([0], float),firms[otherfirm_row,2]-workers[worker_row,5])],float)
            firms[otherfirm_row,3] = production(firms[otherfirm_row,2])
            workers[worker_row,3] = firms[j,0]
            workers[worker_row,4] = correlation
            workers[worker_row,5] = (workers[worker_row,4]+workers[worker_row,1])*PRODUCTIVITY_FACTOR
            firms[j,1] = firms[j,1]+1
            firms[j,2] = firms[j,2]+workers[worker_row,5]
            firms[j,3] = CONS_RETURN*firms[j,2]+math.pow(INC_RETURN*firms[j,2],RETURN_COEFF)
            workers[worker_row,7] = firms[j,3]/firms[j,1]
            #print "iteration",q,"loop emp","worker",workers[worker_row,0]
            break

workers = zeros((NUM_WORKERS,9+SKILLSET_LENGTH))
workers[:,0] = arange(1,NUM_WORKERS+1)
random.seed(RANDOM_SEED*1)
workers[:,1] = random.uniform(0,1,NUM_WORKERS)
workers[:,2] = 5
workers[:,3] = 0
workers[:,4] = 0
random.seed(RANDOM_SEED*2)
workers[:, 9:(9+SKILLSET_LENGTH)] = around(random.uniform(0,1,(NUM_WORKERS,SKILLSET_LENGTH)))

random.seed(RANDOM_SEED*3)
firms = zeros((NUM_FIRMS, 4))
firms[:,0] = arange(1,NUM_FIRMS+1)
firms = hstack((firms,around(random.uniform(0,1,(NUM_FIRMS,SKILLSET_LENGTH)))))

start_full = time.time()

for q in arange(ITERATIONS):
    random.seed(q)
    ordering = random.uniform(0,1,NUM_WORKERS).reshape(-1,1)
    applicants = hstack((workers, ordering))
    applicants = applicants[applicants[:,(size(applicants,axis=1)-1)].argsort(),]

    #Hire workers from unemployment
    start_time = time.time()
    map(hire_unemp, xrange(NUM_FIRMS))
    print "Iteration unemp %2d: %2.5f seconds" % (q, time.time() - start_time)

    #Hire workers from employment
    start_time = time.time()
    map(hire_emp, xrange(NUM_FIRMS))
    print "Iteration emp %2d: %2.5f seconds" % (q, time.time() - start_time)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...