2017-04-26 6 views
1

코드 성능을 향상시키고 자 노력 중이며 다중 처리 모듈을 구현하는 방법을 알지 못합니다. 나는 모든 파일의 메타 데이터를 저장해야이 중첩 루프를 파이썬에서 병렬 처리하는 방법

def start_fetching(directory): 
    with open("test.txt", "a") as myfile: 
     try: 
      for dirpath, dirnames, filenames in os.walk(directory): 
       for current_file in filenames: 
        current_file = dirpath + "/" + current_file 
        myfile.write(current_file) 
      return 0 
     except: 
      return sys.exc_info()[0] 

if __name__ == "__main__": 
    cwd = "/home/" 
    final_status = start_fetching(cwd) 
    exit(final_status) 

을 :

나는 리눅스 (CentOS는 7.2)과 파이썬 2.7

내가 병렬 환경에서 실행하는 데 필요한 코드를 사용하고 (여기서 파일 이름 만 표시됨)을 데이터베이스에 저장합니다. 여기서는 파일 이름 만 텍스트 파일에 저장합니다.

+0

두 번째'for' 루프에서 무언가를 할 때마다 새로운'Thread'를 생성하면됩니다. 평상시와 같이. https://docs.python.org/2/library/threading.html # thread-objects –

+0

[this] (http://stackoverflow.com/questions/29614584/parallel-directory-walk-python) 도움이 될 수 있습니다! –

+2

여러 스레드에서 파일을 동시에 추가하는 것은 일반적으로 좋은 방법이 아닙니다. – jknupp

답변

0

이 스크립트의 처리 시간을 거의 절반으로 줄이는 데 도움을 주셔서 감사합니다.

  1. 가 @KeerthanaPrabhakaran 언급 this 링크를 사용하여 다음을 위해 내가 바란 무엇을 달성하기 위해 두 가지 방법을 발견

    (나는 의견이 많은 콘텐츠를 추가 할 수있는 대답으로이 추가입니다) 이것은 멀티 스레딩과 관련이 있습니다.

    def worker(filename): 
        subprocess_out = subprocess.Popen(["stat", "-c", 
               "INSERT INTO file VALUES (NULL, \"%n\", '%F', %s, %u, %g, datetime(%X, 'unixepoch', 'localtime'), datetime(%Y, 'unixepoch', 'localtime'), datetime(%Z, 'unixepoch', 'localtime'));", filename], stdout=subprocess.PIPE) 
        return subprocess_out.communicate()[0] 
    
    def start_fetching(directory, threads): 
        filename = fetch_filename() + ".txt" 
        with contextlib.closing(multiprocessing.Pool(threads)) as pool: # pool of threads processes 
         with open(filename, "a") as myfile: 
          walk = os.walk(directory) 
          fn_gen = itertools.chain.from_iterable((os.path.join(root, file) for file in files) for root, dirs, files in walk) 
    
          results_of_work = pool.map(worker, fn_gen) # this does the parallel processing 
          print "Concatenating the result into the text file" 
          for result in results_of_work: 
           myfile.write(str(result)) 
        return filename 
    

    는 0m15.154s에서 15203 개 파일을 통과한다.

  2. 두 번째는, @ArunKumar가 언급 한, 멀티에 관련이 :

    def task(filename, process_no, return_dict): 
        subprocess_out = subprocess.Popen(["stat", "-c", 
               "INSERT INTO file VALUES (NULL, \"%n\", '%F', %s, %u, %g, datetime(%X, 'unixepoch', 'localtime'), datetime(%Y, 'unixepoch', 'localtime'), datetime(%Z, 'unixepoch', 'localtime'));", 
               filename], stdout=subprocess.PIPE) 
        return_dict[process_no] = subprocess_out.communicate()[0] 
    
    
    def start_fetching_1(directory): 
        try: 
         processes = [] 
         i = 0 
         manager = multiprocessing.Manager() 
         return_dict = manager.dict() 
    
         for dirpath, dirnames, filenames in os.walk(directory): 
          for current_file in filenames: 
           current_file = dirpath + "/" + current_file 
           # Create Seperate process and do what you want, becausee Multi-threading wont help in parallezing 
           p = multiprocessing.Process(target=task, args=(current_file, i, return_dict)) 
           i += 1 
           p.start() 
           processes.append(p) 
    
         # Let all the child processes finish and do some post processing if needed. 
         for process in processes: 
          process.join() 
    
         with open("test.txt", "a") as myfile: 
          myfile.write(return_dict.values()) 
    
         return 0 
        except: 
         return sys.exc_info()[0] 
    

    이것은 1m12.197s

나는 돈에 15,203 파일을 통과한다 왜 다중 처리가 많은 시간을 필요로하는지 이해하지 못한다. (나의 초기 코드는 0m27.884s를 취하고있다. nly), 거의 100 % CPU를 사용합니다.

위의 코드는 내가 더 위의 코드를 최적화하기 위해 노력하고

(나는 데이터베이스 항목을 만들려면 다음 TEST.TXT 파일을 사용하여 파일에이 정보를 저장하고보다하고), 내가 실행하고 정확한 코드입니다 @CongMa가 언급했듯이 I/O 병목 현상이 발생할 수 있습니다.

+1

요약하면 - 순차적 impl은 0m27.884s, 다중 스레딩은 0m15.154s, 다중 프로세스는 1m12.197s를 차지했습니다. 논리적 인 멀티 스레딩은 작업에 많은 I/O가있는 순차적 인 작업보다 잘 수행됩니다. 그리고 다중 프로세스는 생성 된 프로세스 (15203 개 파일)의 성능을 제대로 수행하지 못했습니다. 이후 우리는 모든 파일에 대해 하나의 프로세스를 생성하고 별도의 작업을 할당했습니다. 프로세스의 생성은 비용이 많이 들고 15K 프로세스는 정말 거대하며 CPU는 이러한 프로세스들 사이에서 스케줄을 잡을 것입니다. 스레드 작성과 동일하지는 않습니다. – arunk2

+0

그게 내가 생각하고 있었던거야. 그리고 훨씬 더 많은 수의 파일 (x10^4 번)에서이 스크립트를 실행할 계획입니다. 당신은 그 수준에서 안정 될 것이라고 생각합니까? –

+0

다중 프로세스는 이러한 대규모 병렬 처리에 대한 접근이 아니어야합니다. 실제 물리적 코어의 <= no.Number의 이점이 있습니다. 리소스 경합으로 인해 멀티 스레드에 이점이 있는지 확실하지 않습니다. 어쨌든 멀티 스레드와 순차적 인 것을 실험 해 보는 것이 좋다. – arunk2

1

큰 작업을 병렬 처리하고 싶습니다. 당신이주는 것은 파일에있는 파일명 일뿐입니다. 모든 스레드 출력마다 별도의 파일을 만들었으므로 나중에 모든 파일을 결합 할 수 있습니다. 이것을 달성하는 다른 방법이 있습니다.

주요 문제가 병렬 처리하는 경우 아래 해결책이 될 수 있습니다.

파이썬은 멀티 스레딩과 멀티 프로세싱을 지원합니다. 멀티 스레딩은 진정으로 병렬 처리가 아니며 IO 블록의 경우 병렬 처리가 가능합니다. 코드를 병렬로 사용하려면 다중 처리 [https://docs.python.org/2/library/multiprocessing.html]]을 사용하십시오. 코드는 아래와 같이 보일 수 있습니다.

from multiprocessing import Process 

def task(filename): 
    with open(filename+"test.txt", "a") as myfile: 
     myfile.write(filename) 

def start_fetching(directory): 
    try: 
     processes = [] 
     for dirpath, dirnames, filenames in os.walk(directory): 
      for current_file in filenames: 
       current_file = dirpath + "/" + current_file 
       # Create Seperate process and do what you want, becausee Multi-threading wont help in parallezing 
       p = Process(target=f, args=(current_file,)) 
       p.start() 
       processes.append(p) 

     # Let all the child processes finish and do some post processing if needed. 
     for process in processes: 
      process.join() 

     return 0 
    except: 
     return sys.exc_info()[0] 

if __name__ == "__main__": 
    cwd = "/home/" 
    final_status = start_fetching(cwd) 
    exit(final_status) 
+0

이것은 틀 렸습니다 @ ArunKumar – Netwave

+0

자세히 설명해 주시겠습니까? – arunk2

+0

프로세스를 시작한 후 즉시 완료 될 때까지 기다리십시오. 여기서 병렬 처리되는 것은 없습니다. – Netwave