Accelerate 라이브러리를 사용하여 여러 GPU에서 LLM 추론

WBOY
풀어 주다: 2023-11-30 17:14:39
앞으로
1255명이 탐색했습니다.

대규모 언어 모델(llm)은 자연어 처리 분야에 혁명을 일으켰습니다. 이러한 모델의 크기와 복잡성이 증가함에 따라 추론을 위한 계산 요구 사항도 크게 증가합니다. 이 문제를 해결하려면 여러 GPU를 활용하는 것이 중요합니다.

Accelerate 라이브러리를 사용하여 여러 GPU에서 LLM 추론

따라서 이 기사에서는 주로 Accelerate 라이브러리 소개, 간단한 방법 및 작업 코드 예제, 다중 GPU를 사용한 성능 벤치마킹을 포함하여 여러 GPU에서 동시에 추론을 수행합니다.

이 기사에서는 여러 3090을 사용하여 여러 GPU에서 llama2-7b의 추론을 확장합니다.

Accelerate 라이브러리를 사용하여 여러 GPU에서 LLM 추론

기본 예제

먼저 Accelerate를 사용하여 다중 GPU "메시지 전달"을 보여주는 간단한 예를 소개합니다.

from accelerate import Accelerator from accelerate.utils import gather_object  accelerator = Accelerator()  # each GPU creates a string message=[ f"Hello this is GPU {accelerator.process_index}" ]   # collect the messages from all GPUs messages=gather_object(message)  # output the messages only on the main process with accelerator.print()  accelerator.print(messages)
로그인 후 복사

출력은 다음과 같습니다.

['Hello this is GPU 0', 'Hello this is GPU 1', 'Hello this is GPU 2', 'Hello this is GPU 3', 'Hello this is GPU 4']
로그인 후 복사

Multi-GPU inference

다음은 간단한 비배치 추론 방법입니다. 코드는 매우 간단합니다. Accelerate 라이브러리가 이미 많은 작업을 수행했기 때문에 직접 사용할 수 있습니다.

from accelerate import Accelerator from accelerate.utils import gather_object from transformers import AutoModelForCausalLM, AutoTokenizer from statistics import mean import torch, time, json  accelerator = Accelerator()  # 10*10 Prompts. Source: https://www.penguin.co.uk/articles/2022/04/best-first-lines-in-books prompts_all=["The King is dead. Long live the Queen.","Once there were four children whose names were Peter, Susan, Edmund, and Lucy.","The story so far: in the beginning, the universe was created.","It was a bright cold day in April, and the clocks were striking thirteen.","It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.","The sweat wis lashing oafay Sick Boy; he wis trembling.","124 was spiteful. Full of Baby's venom.","As Gregor Samsa awoke one morning from uneasy dreams he found himself transformed in his bed into a gigantic insect.","I write this sitting in the kitchen sink.","We were somewhere around Barstow on the edge of the desert when the drugs began to take hold.", ] * 10  # load a base model and tokenizer model_path="models/llama2-7b" model = AutoModelForCausalLM.from_pretrained(model_path,device_map={"": accelerator.process_index},torch_dtype=torch.bfloat16, ) tokenizer = AutoTokenizer.from_pretrained(model_path)   # sync GPUs and start the timer accelerator.wait_for_everyone() start=time.time()  # divide the prompt list onto the available GPUs  with accelerator.split_between_processes(prompts_all) as prompts:# store output of generations in dictresults=dict(outputs=[], num_tokens=0) # have each GPU do inference, prompt by promptfor prompt in prompts:prompt_tokenized=tokenizer(prompt, return_tensors="pt").to("cuda")output_tokenized = model.generate(**prompt_tokenized, max_new_tokens=100)[0] # remove prompt from output output_tokenized=output_tokenized[len(prompt_tokenized["input_ids"][0]):] # store outputs and number of tokens in result{}results["outputs"].append( tokenizer.decode(output_tokenized) )results["num_tokens"] += len(output_tokenized) results=[ results ] # transform to list, otherwise gather_object() will not collect correctly  # collect results from all the GPUs results_gathered=gather_object(results)  if accelerator.is_main_process:timediff=time.time()-startnum_tokens=sum([r["num_tokens"] for r in results_gathered ]) print(f"tokens/sec: {num_tokens//timediff}, time {timediff}, total tokens {num_tokens}, total prompts {len(prompts_all)}")
로그인 후 복사

여러 GPU를 사용하면 약간의 통신 오버헤드가 발생합니다. 성능은 4개의 GPU에서 선형적으로 증가하고 이후에는 이는 특정 설정에서 안정적인 경향이 있습니다. 물론 여기의 성능은 모델 크기 및 양자화, 힌트 길이, 생성된 토큰 수 및 샘플링 전략과 같은 많은 매개변수에 따라 달라지므로 일반적인 사례만 논의합니다.

1 GPU: 44 토큰/초, 시간: 225.5초

2 GPU: 초당 88개 토큰 처리, 총 112.9초 시간

3 GPU: 초당 128개 토큰 처리, 총 77.6초

4 GPU: 137 토큰/초, 시간 : 72.7s

5 GPU: 초당 119개 토큰 처리, 총 소요 시간 83.8초

Accelerate 라이브러리를 사용하여 여러 GPU에서 LLM 추론

여러 GPU에서 일괄 처리

실제 세계에서는 일괄 추론을 사용하여 작업 속도를 높일 수 있습니다. 위로. 이는 GPU 간의 통신을 줄이고 추론 속도를 높입니다. 단일 데이터가 아닌 일괄 데이터를 모델에 입력하려면 prepare_prompts 함수만 추가하면 됩니다.

from accelerate import Accelerator from accelerate.utils import gather_object from transformers import AutoModelForCausalLM, AutoTokenizer from statistics import mean import torch, time, json  accelerator = Accelerator()  def write_pretty_json(file_path, data):import jsonwith open(file_path, "w") as write_file:json.dump(data, write_file, indent=4)  # 10*10 Prompts. Source: https://www.penguin.co.uk/articles/2022/04/best-first-lines-in-books prompts_all=["The King is dead. Long live the Queen.","Once there were four children whose names were Peter, Susan, Edmund, and Lucy.","The story so far: in the beginning, the universe was created.","It was a bright cold day in April, and the clocks were striking thirteen.","It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.","The sweat wis lashing oafay Sick Boy; he wis trembling.","124 was spiteful. Full of Baby's venom.","As Gregor Samsa awoke one morning from uneasy dreams he found himself transformed in his bed into a gigantic insect.","I write this sitting in the kitchen sink.","We were somewhere around Barstow on the edge of the desert when the drugs began to take hold.", ] * 10  # load a base model and tokenizer model_path="models/llama2-7b" model = AutoModelForCausalLM.from_pretrained(model_path,device_map={"": accelerator.process_index},torch_dtype=torch.bfloat16, ) tokenizer = AutoTokenizer.from_pretrained(model_path)  tokenizer.pad_token = tokenizer.eos_token  # batch, left pad (for inference), and tokenize def prepare_prompts(prompts, tokenizer, batch_size=16):batches=[prompts[i:i + batch_size] for i in range(0, len(prompts), batch_size)]batches_tok=[]tokenizer.padding_side="left" for prompt_batch in batches:batches_tok.append(tokenizer(prompt_batch, return_tensors="pt", padding='longest', truncatinotallow=False, pad_to_multiple_of=8,add_special_tokens=False).to("cuda") )tokenizer.padding_side="right"return batches_tok  # sync GPUs and start the timer accelerator.wait_for_everyone() start=time.time()  # divide the prompt list onto the available GPUs  with accelerator.split_between_processes(prompts_all) as prompts:results=dict(outputs=[], num_tokens=0) # have each GPU do inference in batchesprompt_batches=prepare_prompts(prompts, tokenizer, batch_size=16) for prompts_tokenized in prompt_batches:outputs_tokenized=model.generate(**prompts_tokenized, max_new_tokens=100) # remove prompt from gen. tokensoutputs_tokenized=[ tok_out[len(tok_in):] for tok_in, tok_out in zip(prompts_tokenized["input_ids"], outputs_tokenized) ]  # count and decode gen. tokens num_tokens=sum([ len(t) for t in outputs_tokenized ])outputs=tokenizer.batch_decode(outputs_tokenized) # store in results{} to be gathered by accelerateresults["outputs"].extend(outputs)results["num_tokens"] += num_tokens results=[ results ] # transform to list, otherwise gather_object() will not collect correctly  # collect results from all the GPUs results_gathered=gather_object(results)  if accelerator.is_main_process:timediff=time.time()-startnum_tokens=sum([r["num_tokens"] for r in results_gathered ]) print(f"tokens/sec: {num_tokens//timediff}, time elapsed: {timediff}, num_tokens {num_tokens}")
로그인 후 복사

일괄 처리 속도가 크게 빨라지는 것을 확인할 수 있습니다.

다시 작성해야 할 내용은 다음과 같습니다. 1 GPU: 520개 토큰/초, 시간: 19.2초

두 개의 GPU는 초당 900개 토큰의 컴퓨팅 성능을 가지며 계산 시간은 11.1초입니다

3 GPU: 1205 토큰/초, 시간: 8.2s

4 GPU: 1655 토큰/초, 소요 시간: 6.0초

5 GPU: 1658 토큰/초 카드, 시간: 6.0초

Accelerate 라이브러리를 사용하여 여러 GPU에서 LLM 추론

요약

이 글을 기준으로 llama.cpp와 ctransformer는 다중 GPU 추론을 지원하지 않는 것으로 보입니다. 6월에 llama.cpp에 다중 GPU 병합이 있는 것으로 보이지만 공식적인 업데이트는 본 적이 없습니다. , 따라서 당분간 여기에서는 다중 GPU가 지원되지 않는 것으로 확인되었습니다. 여러 GPU를 지원할 수 있다고 확인한 사람이 있으면 메시지를 남겨주세요.

huggingface의 Accelerate 패키지는 여러 GPU를 사용할 수 있는 매우 편리한 옵션을 제공합니다. 추론을 위해 여러 GPU를 사용하면 성능이 크게 향상될 수 있지만 GPU 수가 증가하면 GPU 간 통신 비용이 크게 늘어납니다.

위 내용은 Accelerate 라이브러리를 사용하여 여러 GPU에서 LLM 추론의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:51cto.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿