ChatGLM2-6B icon indicating copy to clipboard operation
ChatGLM2-6B copied to clipboard

[BUG/Help] <多gpu部署6B-32K:如何确保多个张量在同一个gpu上。All tensors should be on the same device when using multiple gpu to run 6B-32k>

Open 1250681923 opened this issue 1 year ago • 13 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Current Behavior

RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cuda:1! (when checking argument for argument tensors in method wrapper_CUDA_cat) Traceback: .... File "/home/h3c/anaconda3/envs/pytorch/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl return forward_call(*args, **kwargs) File "/home/h3c/.cache/huggingface/modules/transformers_modules/chatglm2-6b-32k/modeling_chatglm.py", line 655, in forward presents = torch.cat((presents, kv_cache), dim=0)

Expected Behavior

No response

Steps To Reproduce

How to make sure that presents and kv_cache are on the same device

Environment

- OS: windows
- Python: 3.8
- Transformers: 4.29.1
- PyTorch: 2.0.1+cu118
- CUDA Support: True

Anything else?

No response

1250681923 avatar Aug 08 '23 02:08 1250681923

同问,解决了吗?

xtuhcy avatar Aug 08 '23 03:08 xtuhcy

同问,解决了吗?

还没有,不确定是只有32k会遇见这个问题,还是glm2都会

1250681923 avatar Aug 08 '23 03:08 1250681923

同问,解决了吗?

还没有,不确定是只有32k会遇见这个问题,还是glm2都会

我这里是glm2-32k不行,glm2没问题

xtuhcy avatar Aug 08 '23 03:08 xtuhcy

可以修改一下这个函数, utils.py里面:

def auto_configure_device_map(num_gpus: int) -> Dict[str, int]:
    # transformer.word_embeddings 占用1层
    # transformer.final_layernorm 和 lm_head 占用1层
    # transformer.layers 占用 28 层
    # 总共30层分配到num_gpus张卡上
    num_trans_layers = 28
    per_gpu_layers = 30 / num_gpus
    device_map = {
'transformer.embedding.word_embeddings': 0,
'transformer.encoder.final_layernorm': 3,
'transformer.rotary_pos_emb':0,
'transformer.output_layer': 3,
'transformer.final_layernorm': 0,
 'lm_head': 0}
    used = 2
    gpu_target = 0
    for i in range(num_trans_layers):
        if used >= per_gpu_layers:
            gpu_target += 1
            used = 0
        assert gpu_target < num_gpus
        device_map[f'transformer.encoder.layers.{i}'] = gpu_target
        used += 1

    return device_map

测试可以用:系统ubuntu, 我是四张卡,可以把map的值换成你的卡的序号,两张卡就是0,1,以此类推。 因为layer的划分的问题,可以参考注释来修改,我是改的这样就可以正常运行32k

efwfe avatar Aug 08 '23 05:08 efwfe

可以修改一下这个函数, utils.py里面:

def auto_configure_device_map(num_gpus: int) -> Dict[str, int]:
    # transformer.word_embeddings 占用1层
    # transformer.final_layernorm 和 lm_head 占用1层
    # transformer.layers 占用 28 层
    # 总共30层分配到num_gpus张卡上
    num_trans_layers = 28
    per_gpu_layers = 30 / num_gpus
    device_map = {
'transformer.embedding.word_embeddings': 0,
'transformer.encoder.final_layernorm': 3,
'transformer.rotary_pos_emb':0,
'transformer.output_layer': 3,
'transformer.final_layernorm': 0,
 'lm_head': 0}
    used = 2
    gpu_target = 0
    for i in range(num_trans_layers):
        if used >= per_gpu_layers:
            gpu_target += 1
            used = 0
        assert gpu_target < num_gpus
        device_map[f'transformer.encoder.layers.{i}'] = gpu_target
        used += 1

    return device_map

测试可以用:系统ubuntu, 我是四张卡,可以把map的值换成你的卡的序号,两张卡就是0,1,以此类推。 因为layer的划分的问题,可以参考注释来修改,我是改的这样就可以正常运行32k

具体是如何修改的?请帖下代码谢谢

bk007lz avatar Aug 08 '23 08:08 bk007lz

可以修改一下这个函数, utils.py里面:

def auto_configure_device_map(num_gpus: int) -> Dict[str, int]:
    # transformer.word_embeddings 占用1层
    # transformer.final_layernorm 和 lm_head 占用1层
    # transformer.layers 占用 28 层
    # 总共30层分配到num_gpus张卡上
    num_trans_layers = 28
    per_gpu_layers = 30 / num_gpus
    device_map = {
'transformer.embedding.word_embeddings': 0,
'transformer.encoder.final_layernorm': 3,
'transformer.rotary_pos_emb':0,
'transformer.output_layer': 3,
'transformer.final_layernorm': 0,
 'lm_head': 0}
    used = 2
    gpu_target = 0
    for i in range(num_trans_layers):
        if used >= per_gpu_layers:
            gpu_target += 1
            used = 0
        assert gpu_target < num_gpus
        device_map[f'transformer.encoder.layers.{i}'] = gpu_target
        used += 1

    return device_map

测试可以用:系统ubuntu, 我是四张卡,可以把map的值换成你的卡的序号,两张卡就是0,1,以此类推。 因为layer的划分的问题,可以参考注释来修改,我是改的这样就可以正常运行32k

具体是如何修改的?请帖下代码谢谢

贴的是已经修改后的,主要是device_map的修改,我不知道windows的key是不是一样,不过你可以根据报错对应调整

efwfe avatar Aug 08 '23 09:08 efwfe

可以修改一下这个函数, utils.py里面:

def auto_configure_device_map(num_gpus: int) -> Dict[str, int]:
    # transformer.word_embeddings 占用1层
    # transformer.final_layernorm 和 lm_head 占用1层
    # transformer.layers 占用 28 层
    # 总共30层分配到num_gpus张卡上
    num_trans_layers = 28
    per_gpu_layers = 30 / num_gpus
    device_map = {
'transformer.embedding.word_embeddings': 0,
'transformer.encoder.final_layernorm': 3,
'transformer.rotary_pos_emb':0,
'transformer.output_layer': 3,
'transformer.final_layernorm': 0,
 'lm_head': 0}
    used = 2
    gpu_target = 0
    for i in range(num_trans_layers):
        if used >= per_gpu_layers:
            gpu_target += 1
            used = 0
        assert gpu_target < num_gpus
        device_map[f'transformer.encoder.layers.{i}'] = gpu_target
        used += 1

    return device_map

测试可以用:系统ubuntu, 我是四张卡,可以把map的值换成你的卡的序号,两张卡就是0,1,以此类推。 因为layer的划分的问题,可以参考注释来修改,我是改的这样就可以正常运行32k

具体是如何修改的?请帖下代码谢谢

请问你的问题解决了吗? 我的还是不行 按照引用修改后还是报错

vs0533 avatar Aug 14 '23 05:08 vs0533

可以修改一下这个函数, utils.py里面:

def auto_configure_device_map(num_gpus: int) -> Dict[str, int]:
    # transformer.word_embeddings 占用1层
    # transformer.final_layernorm 和 lm_head 占用1层
    # transformer.layers 占用 28 层
    # 总共30层分配到num_gpus张卡上
    num_trans_layers = 28
    per_gpu_layers = 30 / num_gpus
    device_map = {
'transformer.embedding.word_embeddings': 0,
'transformer.encoder.final_layernorm': 3,
'transformer.rotary_pos_emb':0,
'transformer.output_layer': 3,
'transformer.final_layernorm': 0,
 'lm_head': 0}
    used = 2
    gpu_target = 0
    for i in range(num_trans_layers):
        if used >= per_gpu_layers:
            gpu_target += 1
            used = 0
        assert gpu_target < num_gpus
        device_map[f'transformer.encoder.layers.{i}'] = gpu_target
        used += 1

    return device_map

测试可以用:系统ubuntu, 我是四张卡,可以把map的值换成你的卡的序号,两张卡就是0,1,以此类推。 因为layer的划分的问题,可以参考注释来修改,我是改的这样就可以正常运行32k

具体是如何修改的?请帖下代码谢谢

请问你的问题解决了吗? 我的还是不行 按照引用修改后还是报错

可以贴一下报错的日志吗;还有你的GPU和系统信息

efwfe avatar Aug 16 '23 03:08 efwfe

RuntimeError: CUDA error: invalid device ordina

wxj127 avatar Sep 05 '23 12:09 wxj127

我的 也是 报错

wxj127 avatar Sep 05 '23 12:09 wxj127

可以修改一下这个函数, utils.py里面:

def auto_configure_device_map(num_gpus: int) -> Dict[str, int]:
    # transformer.word_embeddings 占用1层
    # transformer.final_layernorm 和 lm_head 占用1层
    # transformer.layers 占用 28 层
    # 总共30层分配到num_gpus张卡上
    num_trans_layers = 28
    per_gpu_layers = 30 / num_gpus
    device_map = {
'transformer.embedding.word_embeddings': 0,
'transformer.encoder.final_layernorm': 3,
'transformer.rotary_pos_emb':0,
'transformer.output_layer': 3,
'transformer.final_layernorm': 0,
 'lm_head': 0}
    used = 2
    gpu_target = 0
    for i in range(num_trans_layers):
        if used >= per_gpu_layers:
            gpu_target += 1
            used = 0
        assert gpu_target < num_gpus
        device_map[f'transformer.encoder.layers.{i}'] = gpu_target
        used += 1

    return device_map

测试可以用:系统ubuntu, 我是四张卡,可以把map的值换成你的卡的序号,两张卡就是0,1,以此类推。 因为layer的划分的问题,可以参考注释来修改,我是改的这样就可以正常运行32k

具体是如何修改的?请帖下代码谢谢

请问你的问题解决了吗? 我的还是不行 按照引用修改后还是报错

我在上面修改utils.py基础上再修改模型权重目录下的modeling_chatglm.py解决了 大概 655 行位置

if use_cache:
    # token by token decoding, use tuple format
    if kv_caches[0] is not None:
        presents = presents + (kv_cache,)
    # prefilling in decoding, use tensor format to save cuda memory
    else:
        if len(presents) == 0:
            presents = kv_cache
        else:
            presents = torch.cat((presents, kv_cache), dim=0)
 

改为

if use_cache:
    # token by token decoding, use tuple format
    if kv_caches[0] is not None:
        presents = presents + (kv_cache,)
    # prefilling in decoding, use tensor format to save cuda memory
    else:
        if len(presents) == 0:
            presents = kv_cache
        else:
            # 解决 encoder.layers 间传递 device 不一致
             if kv_cache.device != presents.device:
                presents = presents.to(kv_cache.device)
            presents = torch.cat((presents, kv_cache), dim=0)

cenlibin avatar Sep 25 '23 09:09 cenlibin

可以修改一下这个函数, utils.py里面:

def auto_configure_device_map(num_gpus: int) -> Dict[str, int]:
    # transformer.word_embeddings 占用1层
    # transformer.final_layernorm 和 lm_head 占用1层
    # transformer.layers 占用 28 层
    # 总共30层分配到num_gpus张卡上
    num_trans_layers = 28
    per_gpu_layers = 30 / num_gpus
    device_map = {
'transformer.embedding.word_embeddings': 0,
'transformer.encoder.final_layernorm': 3,
'transformer.rotary_pos_emb':0,
'transformer.output_layer': 3,
'transformer.final_layernorm': 0,
 'lm_head': 0}
    used = 2
    gpu_target = 0
    for i in range(num_trans_layers):
        if used >= per_gpu_layers:
            gpu_target += 1
            used = 0
        assert gpu_target < num_gpus
        device_map[f'transformer.encoder.layers.{i}'] = gpu_target
        used += 1

    return device_map

测试可以用:系统ubuntu, 我是四张卡,可以把map的值换成你的卡的序号,两张卡就是0,1,以此类推。 因为layer的划分的问题,可以参考注释来修改,我是改的这样就可以正常运行32k

请问后面的代码需要改吗

faiejir avatar Oct 09 '23 09:10 faiejir

可以修改一下这个函数, utils.py里面:

def auto_configure_device_map(num_gpus: int) -> Dict[str, int]:
    # transformer.word_embeddings 占用1层
    # transformer.final_layernorm 和 lm_head 占用1层
    # transformer.layers 占用 28 层
    # 总共30层分配到num_gpus张卡上
    num_trans_layers = 28
    per_gpu_layers = 30 / num_gpus
    device_map = {
'transformer.embedding.word_embeddings': 0,
'transformer.encoder.final_layernorm': 3,
'transformer.rotary_pos_emb':0,
'transformer.output_layer': 3,
'transformer.final_layernorm': 0,
 'lm_head': 0}
    used = 2
    gpu_target = 0
    for i in range(num_trans_layers):
        if used >= per_gpu_layers:
            gpu_target += 1
            used = 0
        assert gpu_target < num_gpus
        device_map[f'transformer.encoder.layers.{i}'] = gpu_target
        used += 1

    return device_map

测试可以用:系统ubuntu, 我是四张卡,可以把map的值换成你的卡的序号,两张卡就是0,1,以此类推。 因为layer的划分的问题,可以参考注释来修改,我是改的这样就可以正常运行32k

请问后面的代码需要改吗

我是改成这个好的

device_map = {
        'transformer.embedding.word_embeddings': 0,
        'transformer.encoder.final_layernorm': 0,
        'transformer.prefix_encoder': 0,
        'transformer.output_layer': 0,
        'transformer.rotary_pos_emb': 0,
        'lm_head': 0
    }

光改transformer.prefix_encoder.embedding.weight是不够的

jingyaogong avatar Nov 18 '23 13:11 jingyaogong