[PYTHON] TFRecordReader가 매우 느리게 보이고 멀티 스레드 읽기가 작동하지 않습니다.
PYTHONTFRecordReader가 매우 느리게 보이고 멀티 스레드 읽기가 작동하지 않습니다.
내 훈련 과정은 기차 및 평가 데이터 세트에 tfrecord 형식을 사용합니다.
필자는 독자의 벤치 마크 테스트를 8000 건 / 초 밖에하지 않습니다. 및 io 속도 (iotop 명령에서 볼 수 있음)는 단지 400KB-500KB / s입니다.
protobuf의 cpp 버전을 사용하고 있습니다.
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/g3doc/get_started/os_setup.md#protobuf-library-related-issues
가능한 경우 최소한의 재현 가능한 예제를 제공하십시오 (일반적으로 수백 줄의 코드를 읽을 시간이 없습니다)
def read_and_decode(filename_queue):
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
return serialized_example
serialized_example = read_and_decode(filename_queue)
batch_serialized_example = tf.train.shuffle_batch(
[serialized_example],
batch_size=batch_size,
num_threads=thread_number,
capacity=capacity,
min_after_dequeue=min_after_dequeue)
features = tf.parse_example(
batch_serialized_example,
features={
"label": tf.FixedLenFeature([], tf.float32),
"ids": tf.VarLenFeature(tf.int64),
"values": tf.VarLenFeature(tf.float32),
})
시도한 다른 시도한 해결책은 무엇입니까?
tf.train.shuffle_batch에서 num_threads를 설정하려고했지만 작동하지 않습니다.
그것은 2 스레드로 설정하면, 그것은 8000records / s에서, 스레드 번호를 확대하면, 그것은 느리게 얻을 것으로 보인다. (나는 CPU를 소모하는 모든 연산을 제거한다. 단지 데이터를 읽는다.)
내 서버는 24 코어 CPU입니다.
해결법
-
==============================
1.여기서 문제는 각 session.run에 대한 고정 비용 오버 헤드가 있으며 대기열에 많은 예제가있는 대기열을 채우는 것이 느려지 게된다는 것입니다.
여기서 문제는 각 session.run에 대한 고정 비용 오버 헤드가 있으며 대기열에 많은 예제가있는 대기열을 채우는 것이 느려지 게된다는 것입니다.
특히 각 session.run은 약 100-200 usec이므로 초당 약 5k-10k session.run 호출 만 수행 할 수 있습니다.
파이썬 프로파일 링 (파이썬 -m cProfile)을 수행하는 경우이 문제는 명백하지만 타임 라인 프로파일 또는 CPU 프로파일에서 시작하는 경우보기가 어렵습니다.
해결 방법은 enqueue_many를 사용하여 대기열에 일괄 적으로 항목을 추가하는 것입니다. 나는 당신의 벤치 마크를 https://gist.github.com/ericyue/7705407a88e643f7ab380c6658f641e8에서 가져 와서 .run 호출마다 많은 항목을 대기열에 넣기 위해 수정했다. 그리고 그것은 10 배의 속도 향상을 준다.
수정은 다음과 같이 tf.batch 호출을 수정하는 것입니다.
if enqueue_many: reader = tf.TFRecordReader(options = tf.python_io.TFRecordOptions(tf.python_io.TFRecordCompressionType.ZLIB)) queue_batch = [] for i in range(enqueue_many_size): _, serialized_example = reader.read(filename_queue) queue_batch.append(serialized_example) batch_serialized_example = tf.train.shuffle_batch( [queue_batch], batch_size=batch_size, num_threads=thread_number, capacity=capacity, min_after_dequeue=min_after_dequeue, enqueue_many=True)
전체 소스를 보려면 여기를 확인하십시오. https://github.com/yaroslavvb/stuff/blob/master/ericyue-slowreader/benchmark.py
이제 대부분의 시간이 대기열 작업에 소요되기 때문에 훨씬 빠르게 진행되도록 최적화하는 것은 어렵습니다. 정수를 대기열에 추가하는 버드 다운 버전을 보면 비슷한 속도를 얻을 수 있으며 타임 라인을 볼 때 대기열에서 대기하는 데 소요되는 시간을 알 수 있습니다.
각 dequeue op에는 약 60 usec가 소요되지만 병렬로 실행되는 평균 5 개이므로 dequeue 당 12 usec가 발생합니다. 즉, 최상의 경우 초당 200,000 개 이하의 예제를 얻을 수 있습니다.
-
==============================
2.다음은 야로 슬라브 (Yaroslav)의 대답에 대한 간단한 속도 향상 건물입니다.
다음은 야로 슬라브 (Yaroslav)의 대답에 대한 간단한 속도 향상 건물입니다.
Tensorflow에는 tf.TFRecordReader.read_up_to 함수가 내장되어있어 각 session.run () 호출에서 여러 레코드를 읽으며 여러 호출로 인해 발생하는 초과 오버 헤드를 제거합니다.
enqueue_many_size = SOME_ENQUEUE_MANY_SIZE reader = tf.TFRecordReader(options = tf.python_io.TFRecordOptions(tf.python_io.TFRecordCompressionType.ZLIB)) _, queue_batch = reader.read_up_to(filename_queue, enqueue_many_size) batch_serialized_example = tf.train.shuffle_batch( [queue_batch], batch_size=batch_size, num_threads=thread_number, capacity=capacity, min_after_dequeue=min_after_dequeue, enqueue_many=True)
Yaroslav의 답변에서와 같이 배치 함수가 여러 레코드를 받아들이도록 enqueue_many = True를 설정해야합니다.
제 유스 케이스에서는 매우 빨랐습니다.
-
==============================
3.야로 슬라브의 대답에 대한 부록 : tf.python_io.tf_record_iterator를 사용하여 예제를 반복하여 목록에 추가하면 enquue_many = true로 tf.train.shuffle_batch에 전달할 수 있습니다.
야로 슬라브의 대답에 대한 부록 : tf.python_io.tf_record_iterator를 사용하여 예제를 반복하여 목록에 추가하면 enquue_many = true로 tf.train.shuffle_batch에 전달할 수 있습니다.
queue_batch = [] for serialized_example in tf.python_io.tf_record_iterator(filename,options = tf.python_io.TFRecordOptions(tf.python_io.TFRecordCompressionType.ZLIB)): queue_batch.append(serialized_example) batch_serialized_example = tf.train.shuffle_batch( [queue_batch], batch_size=batch_size, num_threads=thread_number, capacity=capacity, min_after_dequeue=min_after_dequeue, enqueue_many=True)
reader.read ()를 사용하여 예제를 반복 할 경우 일괄 처리 당 하나의 읽기가 발생합니다. 즉, n 번째 배치는 batch_num 많은 고유 레코드보다는 n 번째 레코드의 batch_num 사본이됩니다.
from https://stackoverflow.com/questions/41647784/tfrecordreader-seems-extremely-slow-and-multi-threads-reading-not-working by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] OpenCV + Python + Mac으로 비디오 쓰기 (0) | 2018.11.04 |
---|---|
[PYTHON] Python을 통해 Windows 콘솔 응용 프로그램과 상호 작용 (0) | 2018.11.04 |
[PYTHON] Python에서 Openpyxl을 사용하여 기존 Excel 파일 수정 (0) | 2018.11.03 |
[PYTHON] Matplotlib : 선택 영역을 마우스로 직사각형 모양으로 그립니다. (0) | 2018.11.03 |
[PYTHON] 어떻게 파이썬에서 @debuggable 데코레이터를 작성하겠습니까? (0) | 2018.11.03 |