Самый быстрый ввод-вывод в Python 3? - PullRequest
14 голосов
/ 02 ноября 2011

Я решил несколько проблем на SPOJ.pl, используя python 3.1.2, и некоторые люди, быстро получившие ответы на простые проблемы, заставляют меня задуматься, есть ли более быстрый способ обработки ввода и вывода.

Я пытался использовать

input()
print()

и

sys.stdin.readline()
sys.stdout.write()

а точнее

for line in sys.stdin:
    #Handle input
    sys.stdout.write(output)

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

Но все это приводит к одинаковому времени выполнения.

Есть ли более быстрый способ обработки ввода и вывода из stdin / out?

Ответы [ 3 ]

10 голосов
/ 02 ноября 2011

Следующее, вероятно, будет самым быстрым:

  1. Считывание всех входных данных одновременно, используя os.read(0, some_big_enough_number).

  2. Обработка выходных данных, сборрезультаты в виде списка results.

  3. Запишите все результаты сразу, используя os.write(1, "".join(results)).

Я помню один случай, когда язаметил, что os.read() и os.write() иногда быстрее, чем при использовании Python I / O, но я не помню деталей.

2 голосов
/ 02 ноября 2011

SPOJ позволяет выбирать среди множества языков программирования.Сравниваете ли вы время выполнения с другими решениями, написанными на других языках программирования?

Ради интереса я представил следующие решения первой проблемы (кодовое имя TEST) для сравнения времени выполнения.

*Решение 1005 * C ++ (G ++ 4.3.2)
#include <iostream>
int main ( int, char** )
{
     for ( int number=0; (std::cin >> number) && (number != 42); ) {
         std::cout << number << std::endl;
     }
}

См. Представление .

Решение Python (2.5)

import sys
for line in sys.stdin:
    number = int(line)
    if number == 42:
        break
    print number

См. представление .

Заключение

Я не уверен на 100%, что это дает абсолютную лучшую производительность в обоих языках, но там не так много кода для оптимизации.

Я получаю измерение времени 0.00 для измерения C ++ и 0.04 для кода Python.Предполагая, что последовательность чисел, представленных в обе программы, одинакова, я думаю, что сравнение времени выполнения с решениями на других языках почти бессмысленно (см. Следующий параграф).

Теперь это справедливо только для простых задач.Наиболее сложные проблемы требуют выбора правильного алгоритма для проблемы, а выбор неправильного имеет радикальные последствия.В этих случаях тщательно созданные решения Python могут все еще быть медленнее, чем тщательно созданные решения C ++, но хорошее решение Python превзойдет наивное решение, написанное на любом другом языке.

2 голосов
/ 02 ноября 2011

Вероятно, нет.

В конце концов, print вызовет sys.stdout.write(). Но поскольку print является встроенной функцией, возможно, реализованной в C, она может быть даже быстрее, чем вызов sys.stdout.write().

Поскольку все операции ввода-вывода должны проходить через объект, который возвращает sys.stdout, это узкое место. То же самое верно для sys.stdin.

Нет волшебных трюков, чтобы сделать это быстрее.

Если вам нужен более быстрый ввод-вывод, попробуйте следующее:

  • Запись в файл вместо
  • Использовать буферизованный ввод-вывод (стандартный вывод канала с помощью команды buffer в небольшом сценарии оболочки).
  • Использовать отображенный в памяти файл
  • Убедитесь, что процесс, который читает ваш вывод, может идти в ногу. Например, консоль DOS довольно медленная. Если вы передадите вывод через медленную команду, это может заблокировать ваш процесс Python.

[EDIT] Похоже, SPOJ.pl - это своего рода сайт для программистов. В этом случае скорость ввода-вывода не является причиной: вы использовали неверный алгоритм для решения проблемы.

Разница в скорости между хорошей и удовлетворительной производительностью может легко составлять от 10 до 100 000 раз. Изменив несколько строк кода, я однажды мог заставить код выполняться менее чем за 5 секунд, что заняло 45 минут.

...