2014-02-06 4 views
3

Я играл с Julia, потому что он кажется синтаксически похожим на python (который мне нравится), но утверждает, что он быстрее. Тем не менее, я попытался сделать подобный сценарий то, что я имею в питоне для tesing, где числовые значения находятся в текстовом файле, который использует эту функцию:Попробуйте поймать или напечатать преобразование в julia - (Julia 73 секунды, Python 0,5 секунды)

function isFloat(s) 
    try: 
     float64(s) 
     return true 
    catch: 
     return false 
    end 
end 

По какой-то причине, это занимает много времени для текста файл с разумным количеством строк текста (~ 500000).
Зачем это было? Есть лучший способ сделать это? Какую общую особенность языка я могу понять из этого, чтобы применить ее к другим языкам?

Вот два точных сценарии я побежал со временем для справки:

питона: ~ 0,5 секунды

def is_number(s): 
    try: 
     np.float64(s) 
     return True 
    except ValueError: 
     return False 

start = time.time() 
file_data = open('SMW100.asc').readlines() 
file_data = map(lambda line: line.rstrip('\n').replace(',',' ').split(), file_data) 

bools = [(all(map(is_number, x)), x) for x in file_data] 
print time.time() - start 

Жюлиа: ~ 73,5 секунд

start = time() 
function isFloat(s) 
    try: 
     float64(s) 
     return true 
    catch: 
     return false 
    end 
end 
x = map(x-> split(replace(x, ",", " ")), open(readlines, "SMW100.asc")) 

u = [(all(map(isFloat, i)), i) for i in x] 

print(start - time()) 
+0

Я не знаю о производительности try/catch, но чтобы проверить, имеет ли данный файл только поплавки, вы можете попробовать использовать функцию readdlm (http://docs.julialang.org/en/latest/stdlib/ base/# Base.readdlm), который вернет Array {Float64} в случае, если это возможно (тогда вы можете просто проверить тип возвращаемого массива). –

ответ

5

Обратите внимание, что вы также можете использовать функцию float64_isvalid в стандартной библиотеке, чтобы (a) проверить, является ли строка допустимым значением с плавающей запятой, и (b) вернуть значение.

Заметим также, что колоны (:) после try и catch в вашем isFloat кода неверны в Джулии (это Pythonism).

Намного более быстрая версия кода должна быть:

const isFloat2_out = [1.0] 
isFloat2(s::String) = float64_isvalid(s, isFloat2_out) 

function foo(L) 
    x = split(L, ",") 
    (all(isFloat2, x), x) 
end 

u = map(foo, open(readlines, "SMW100.asc")) 

На моей машине, для файла образца с 100000 строк и 10 столбцов данных, 50% из которых являются действительные числа, ваш код Python принимает 4,21 секунды, а мой код Юлии занимает 2,45 секунды.

+0

Спасибо за ответ, я попробовал просто удалить ':', и он ускорил его с 73 секунд до 0,6 секунды, так что это была серьезная проблема. Было бы полезно, если бы он сделал ошибку об использовании ':' в неправильном месте, если это вызывает много проблем, но все же странно компилируется. – chase

+0

Необходимость декларации 'const' в вашем коде странна для меня как персонажа, не являющегося членом CS. Я знаю, что у Джулии есть некоторые проблемы с глобальными переменными, которые, как представляется, являются 'isFloat2_out', но также я смущен тем, почему эта функция написана таким образом. Является ли это модификацией на месте 'isFloat2_out'? Что было бы неправильным в том, чтобы использовать его для возврата логического значения типа 'b = float64_isvalid (" 1.2 ")', которое должно использоваться как 'u = [(all (map (float64_isvalid, i)), i) для i в x]' ? – chase

+0

Я хочу знать, что ':' делает здесь. ': something' делает символ': (1 + 1) 'цитирует код, возвращающий' (+ (1,1)) '. Ладно, у меня это получилось. В этом случае что происходит? Вот странный пример: 'julia> try: println (" hi "); return true end'. Это возвращает «ложь» без всякой причины, которую я могу себе представить. –

5

Это интересно которые могут стоить представить julia-пользователям, чтобы получить более целенаправленную обратную связь, чем SO, вероятно, предоставит. На первый взгляд, я думаю, что вы сталкиваетесь с проблемами, потому что (1) try/catch выполняется чуть медленнее, а затем (2) вы используете try/catch в контексте, где существует очень большая неопределенность типа из-за множества вызовов функций, которые не возвращают стабильные типы. В результате интерпретатор Джулии тратит свое время на то, чтобы выяснить типы объектов, а не выполнять свои вычисления. Трудно сказать, где большие узкие места, потому что вы делаете много вещей, которые не очень идиоматичны в Джулии. Кроме того, вы, кажется, выполняете свои вычисления в глобальной области, где компилятор Джулии не может выполнять много значимых оптимизаций из-за дополнительной неопределенности типа.

3

Python странно неоднозначен в отношении того, являются ли использование исключений для потока управления хорошим или плохим. См. Python using exceptions for control flow considered bad?. Но даже в Python консенсус в том, что код пользователя не должен использовать исключения для потока управления (хотя по какой-то причине генераторам разрешено это делать). Таким образом, в основном простой ответ заключается в том, что вы не должны этого делать - исключения для исключительных ситуаций, а не для потока управления. Вот почему почти нулевые усилия были направлены на то, чтобы сделать конструкцию try/catch Джулии быстрее - вы не должны использовать ее в первую очередь. Конечно, в какой-то момент мы, вероятно, обойдемся быстрее.

Сказанное относится к нам как разработчикам стандартной библиотеки Джулии, чтобы убедиться, что мы предоставляем API, которые никогда не заставляют вас использовать исключения для потока управления. В этом случае вам нужна функция, которая позволяет попытаться проанализировать что-то как значение с плавающей запятой и указать, возможно ли это или нет, а не путем исключения исключения, а путем возврата нормальных значений. Мы не предоставляем такой API, так что это, в конечном счете, недостаток стандартной библиотеки Джулии - как она существует прямо сейчас. Я открыл вопрос, чтобы обсудить этот вопрос по дизайну API: https://github.com/JuliaLang/julia/issues/5704. Посмотрим, как он вытащит.

+3

Фактически мы предоставляем такой API в данном конкретном случае ('float64_isvalid'), как указано ниже. –

+1

Спасибо за ответ @StefanKarpinski Я не понял, что попытка поймать может быть такой плохой практикой. Когда я писал скрипт на python, у меня было ощущение, что это не похоже на хорошее решение только потому, что это казалось тривиальной задачей, занятой несколькими пользовательскими строками кода - очень редко в python. Тем не менее, все заверили меня, что это правильный ответ, поэтому я сохранил его - приятно знать, что я не совсем ошибался. – chase

+0

На самом деле, я не думаю, что Python неоднозначен. Это обычная, принятая и даже продвинутая идиома. Один из основных разработчиков dev на Python суммирует его намного лучше, чем я мог в его ответе [здесь] (http://stackoverflow.com/questions/16138232/is-it-a-good-practice-to-use-try-except -else-in-python) – Gerrat

 Смежные вопросы

  • Нет связанных вопросов^_^