Skip to content

Commit 2d01edf

Browse files
authored
feat: add file lock for remote files download to local path when multiple thread environment. (#1887)
1 parent b4132be commit 2d01edf

File tree

4 files changed

+59
-8
lines changed

4 files changed

+59
-8
lines changed

examples/parallel/bert_imdb_finetune/bert_imdb_finetune_cpu_mindnlp_trainer_npus_same.py renamed to llm/parallel/bert_imdb_finetune_dp/bert_imdb_finetune_cpu_mindnlp_trainer_npus_same.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,14 @@ def tokenize(text):
6262
model = AutoModelForSequenceClassification.from_pretrained('bert-base-cased', num_labels=2)
6363

6464
from mindnlp.engine import TrainingArguments
65-
6665
training_args = TrainingArguments(
6766
output_dir="bert_imdb_finetune_cpu",
6867
save_strategy="epoch",
6968
logging_strategy="epoch",
7069
num_train_epochs=2.0,
7170
learning_rate=2e-5
7271
)
73-
training_args = training_args.set_optimizer(name="adamw", beta1=0.8) # 手动指定优化器,OptimizerNames.SGD
72+
training_args = training_args.set_optimizer(name="adamw", beta1=0.8) # Manually specify the optimizer, OptimizerNames.SGD
7473

7574
trainer = Trainer(
7675
model=model,

examples/parallel/bert_imdb_finetune/bert_imdb_finetune_npu_mindnlp_trainer.sh renamed to llm/parallel/bert_imdb_finetune_dp/bert_imdb_finetune_npu_mindnlp_trainer.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ echo "==========================================="
88
EXEC_PATH=$(pwd)
99
if [ ! -d "${EXEC_PATH}/data" ]; then
1010
if [ ! -f "${EXEC_PATH}/emotion_detection.tar.gz" ]; then
11-
wget wget https://baidu-nlp.bj.bcebos.com/emotion_detection-dataset-1.0.0.tar.gz -O emotion_detection.tar.gz
11+
wget https://baidu-nlp.bj.bcebos.com/emotion_detection-dataset-1.0.0.tar.gz -O emotion_detection.tar.gz
1212
fi
1313
tar xvf emotion_detection.tar.gz
1414
fi

mindnlp/utils/download.py

+25-5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import json
2424
import types
2525
import functools
26+
import sys
2627
import tempfile
2728
import time
2829
from typing import Union, Optional, Dict, Any
@@ -91,7 +92,7 @@ def download_url(url, proxies=None):
9192
Returns:
9293
`str`: The location of the temporary file where the url was downloaded.
9394
"""
94-
return http_get(url, tempfile.gettempdir(), download_file_name='tmp_' + url.split('/')[-1], proxies=proxies)
95+
return threads_exclusive_http_get(url, tempfile.gettempdir(), download_file_name='tmp_' + url.split('/')[-1], proxies=proxies)
9596

9697
def copy_func(f):
9798
"""Returns a copy of a function f."""
@@ -142,6 +143,25 @@ def get_cache_path():
142143
return cache_dir
143144

144145

146+
def threads_exclusive_http_get(url, storage_folder=None, md5sum=None, download_file_name=None, proxies=None, headers=None):
147+
pointer_path = os.path.join(storage_folder, download_file_name)
148+
lock_file_path = pointer_path + ".lock"
149+
if sys.platform != "win32":
150+
import fcntl # pylint: disable=import-error
151+
else:
152+
import winfcntlock as fcntl # pylint: disable=import-error
153+
with open(lock_file_path, 'w') as lock_file:
154+
fd = lock_file.fileno()
155+
try:
156+
fcntl.flock(fd, fcntl.LOCK_EX)
157+
file_path = http_get(url, path=storage_folder, download_file_name=download_file_name, proxies=proxies, headers=headers)
158+
return file_path
159+
except Exception as exp:
160+
raise exp
161+
finally:
162+
fcntl.flock(fd, fcntl.LOCK_UN)
163+
164+
145165
def http_get(url, path=None, md5sum=None, download_file_name=None, proxies=None, headers=None):
146166
r"""
147167
Download from given url, save to path.
@@ -628,11 +648,11 @@ def download(
628648
else:
629649
headers = {}
630650
try:
631-
pointer_path = http_get(url, storage_folder, download_file_name=relative_filename, proxies=proxies, headers=headers)
632-
except Exception:
651+
pointer_path = threads_exclusive_http_get(url, storage_folder, download_file_name=relative_filename, proxies=proxies, headers=headers)
652+
except Exception as exp:
633653
# Otherwise, our Internet connection is down.
634654
# etag is None
635-
raise
655+
raise exp
636656

637657
return pointer_path
638658

@@ -723,7 +743,7 @@ def get_from_cache(
723743
if os.path.exists(file_path) and check_md5(file_path, md5sum):
724744
return file_path
725745
try:
726-
path = http_get(url, cache_dir, md5sum, download_file_name=filename, proxies=proxies)
746+
path = threads_exclusive_http_get(url, cache_dir, md5sum, download_file_name=filename, proxies=proxies)
727747
return path
728748
except (ProxyError, SSLError) as exc:
729749
raise exc

mindnlp/utils/winfcntlock.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright 2020 The HuggingFace Team. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# ============================================================================
15+
"""fcntl replacement for Windows."""
16+
import win32con # pylint: disable=import-error
17+
import pywintypes # pylint: disable=import-error
18+
import win32file # pylint: disable=import-error
19+
20+
21+
LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
22+
LOCK_SH = 0 # The default value
23+
LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
24+
__overlapped = pywintypes.OVERLAPPED()
25+
26+
def lock(file, flags):
27+
hfile = win32file._get_osfhandle(file.fileno())
28+
win32file.LockFileEx(hfile, flags, 0, 0xffff0000, __overlapped)
29+
30+
def unlock(file):
31+
hfile = win32file._get_osfhandle(file.fileno())
32+
win32file.UnlockFileEx(hfile, 0, 0xffff0000, __overlapped)

0 commit comments

Comments
 (0)