Словарное назначение вылетает Cython - PullRequest
0 голосов
/ 28 мая 2018

Приведенный ниже код Cython вылетает из-за оператора word_idxs[token] = row.Если я уберу это утверждение, все будет работать нормально.Вот мои наблюдения

  1. Код отлично работает, когда в качестве аргумента указан другой файл
  2. Я попытался напечатать token, программа вылетает при разных значениях token при разныхраз (это не определенное слово, которое вызывает ошибку)
  3. Я попытался присвоить word_idxs[row]=row, и ошибка повторяется.Поэтому я думаю, что ошибка не имеет ничего общего со строками, в частности
  4. Если я продолжаю назначать одну и ту же клавишу, ошибка не возникает.Например: word_idxs['constant'] = row
  5. Если я удаляю cmatrix[row, col] = fval, то снова все работает

Я новичок в Cython, пожалуйста, укажите, если я делаю что-то в корне неправильно

 def cload(self, file_path, int dim, long vocab_size):
    print("Loading")
    cdef:
        unsigned int row = 0
        int col = 0
        float [:,:] cmatrix
        cdef dict word_idxs = {}
        char* token
        char* line

    matrix = np.zeros([vocab_size, dim], dtype=np.dtype('f'))
    cmatrix = matrix

    with open(file_path, 'rb') as f:
        for line in f:
            token = strtok(line, ' \n')
            print(row, token)

            word_idxs[token] = row

            for col in range(dim) :
                val = strtok(NULL,' ')
                fval = atof(val)
                cmatrix[row, col] = fval
            row += 1

1 Ответ

0 голосов
/ 28 мая 2018

Самая очевидная проблема для меня заключается в том, что у вас нет проверки ошибок на выходе token или val.Это может быть NULL, если strtok достигает конца строки, и вы просто не справляетесь с этим.Из-за отсутствия поддающегося проверке примера трудно понять, что является реальной проблемой

Затем в комментариях @ead было отмечено несколько проблем:

  1. PythonСтроки должны быть неизменными, но strtok изменяет указатель, который он дал.Это вряд ли вызовет сбой, который вы видите, но может вызвать проблемы с Python.

  2. line, скорее всего, неверный указатель, как только он создан (поскольку объект Python основан наникогда не хранится)

Я думаю, что эти проблемы можно решить с помощью чего-то вроде

cdef char* line_ptr
for line in f: # line IS NOT TYPED
  line_ba = bytearray(line) # bytearray is mutable - changing it is fine
  line_ptr = line_ba # line_ptr is valid as long as line_ba exists

И в вашем коде, и в предложенной мной замене есть много преобразований между Pythonи C-строки, которые никогда не бывают чрезвычайно быстрыми (и их трудно получить правильно).Это похоже на то, что было бы проще написать на Python - я сомневаюсь, что вы действительно извлекаете выгоду из вызовов Си.

...