как ускорить конвертацию cpython.datetime - PullRequest
0 голосов
/ 22 апреля 2019

Я пытаюсь ускорить преобразование строки в дату. Я предпочел Cython. После того, как я получил c tm struct. Я конвертирую tm struct в python datetime с помощью функции cpython.datetime.date. Оно работает. Примерно на 50% ускорение обнадеживает. Но мой код теряет время cpython.datetime.date функции. Есть ли более эффективный подход для этого преобразования. Я делюсь своими кодами ниже. Код написан не аккуратно. Но я надеюсь, что будет полезно понять, что я пытаюсь сделать.

Спасибо.

cimport cython
from cython.parallel import prange, parallel
from cpython.datetime cimport date, PyDateTime_Date
cimport numpy as np

import numpy as np
import pandas as pd
from libc.stdlib cimport atoi, malloc, free
from libc.string cimport strcpy, strncpy
from libc.stdio cimport sprintf
from cpython.datetime cimport import_datetime
import_datetime()


cdef extern from "time.h" nogil:
    ctypedef long time_t
    struct tm:
        int    tm_sec   
        int    tm_min   
        int    tm_hour  
        int    tm_mday  
        int    tm_mon   
        int    tm_year  
        int    tm_wday  
        int    tm_yday  
        int    tm_isdst 
    time_t mktime(tm *timeptr)
    char *strptime(const char *s, const char *format, tm *tm)

@cython.boundscheck(False)
@cython.wraparound(False)
def convert_date_fast(np.int32_t[::1] date_vec):
    cdef int i, d_year, d_month, d_day, t_hour, t_min, t_sec, t_ms, j
    cdef int N = len(date_vec)

Я выбираю тип объекта здесь. Я думаю, эта часть может быть узким местом.

cdef np.ndarray[object] out_ar2 = np.empty(N, dtype=object)

cdef tm *out_ar = <tm *> malloc(N * sizeof(tm))
cdef char *date_str = <char *> malloc(N * 8 * sizeof(char) )
cdef tm result;


with nogil, parallel():
    for i in prange(N):
         sprintf(&date_str[i*8], "%d", date_vec[i])
         strptime(&date_str[i*8],"%Y%m%d",&out_ar[i])

out_ar2 - это трудоемкая часть всего кода.

    for j in range(N):
        out_ar2[j] = date(out_ar[j].tm_year + 1900, out_ar[j].tm_mon + 1, out_ar[j].tm_mday)


    free(out_ar)
    free(date_str)

    return(out_ar2)
...