Trong bài đăng này, chúng tôi nói về cách sao chép dữ liệu từ quy trình gốc sang một số quy trình worker trong
CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
9 bằng cách sử dụng các biến toàn cục. Cụ thể, chúng tôi sẽ sử dụng các thuộc tính lớp, vì tôi thấy giải pháp này hấp dẫn hơn một chút so với sử dụng các biến toàn cục được xác định ở đầu tệpĐối với những bạn mới tham gia loạt bài này, vấn đề chúng tôi đang cố gắng giải quyết như sau…
Cho lớp sau
class IntToBitarrayConverter[]:
def set_bitstring_cache[self, bitstring_cache: Dict]:
self.bitstring_cache = bitstring_cache
def convert[self, integer: int] -> np.ndarray:
bitstring = self.bitstring_cache[integer]
# cache the step of bitstring = format[integer, 'b']
return self._bitstring_to_ndarray[bitstring]
@staticmethod
def _bitstring_to_ndarray[bitstring] -> np.ndarray:
arr = [np.fromstring[bitstring, 'u1'] - 48]
return arr
Và đưa ra sự song song sau đây của phương pháp
CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
0 của chúng tôi bằng cách sử dụng CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
1CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
Chúng tôi đã học được rằng khi bạn có một phương thức thể hiện với một đối tượng lớn được liên kết với nó, việc chuyển phương thức này sang
CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
2 sẽ dẫn đến mất hiệu suất rất lớn do lặp lại quá trình tuần tự hóa/giải tuần tự hóa đối tượng lớn giữa các quy trìnhĐây là những gì đã xảy ra với phương pháp
CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
0 của chúng tôi ở trên. Trong bài đăng này, chúng tôi khám phá một giải pháp chỉ cho chúng tôi “cách truyền dữ liệu đến Nhóm công nhân và chỉ thực hiện một lần. ”Một giải pháp sang trọng
Câu trả lời đáng tiếc cho câu hỏi của chúng tôi ở trên là, với cách triển khai hiện tại của
CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
1, chúng tôi cần sử dụng các biến toàn cục để truyền dữ liệu tới CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
5 của chúng tôi. Hầu hết các tài nguyên liên mạng sẽ cho bạn thấy ví dụ tương tự nàyBằng cách thực hiện một cách tiếp cận khác, chúng ta có thể phân loại điều này một chút bằng cách sử dụng các thuộc tính lớp và một
CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
0, với hy vọng rằng chúng ta có thể bảo tồn một cách tinh vi một số hình thức đóng gói trong mã của mìnhNhập
CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
1class ClassMethodBitarrayConverter[IntToBitarrayConverter]:
bitstring_cache = None
@classmethod
def set_bitstring_cache[cls, bitstring_cache: Dict]:
cls.bitstring_cache = bitstring_cache
@classmethod
def convert[cls, integer: int, init_return=None] -> np.ndarray:
bitstring = cls.bitstring_cache[integer]
return cls._bitstring_to_ndarray[bitstring]
Chúng tôi kế thừa từ
CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
2 và thực hiện ba thay đổi
3 trở thành một thuộc tính của lớpCACHE_SIZE = 1024 * 1024 # 1 MB ITER_SIZE = 1000000 # 1 million int_to_bitarr_converter = IntToBitarrayConverter[] int_to_bitarr_converter.set_bitstring_cache[ {key: format[key, 'b'] for key in range[CACHE_SIZE]}] with Pool[] as pool: ndarray_bitarr_ls = pool.map[ int_to_bitarr_converter.convert, [random.randint[0, CACHE_SIZE - 1] for _ in range[ITER_SIZE]]]]
0 trở thành mộtCACHE_SIZE = 1024 * 1024 # 1 MB ITER_SIZE = 1000000 # 1 million int_to_bitarr_converter = IntToBitarrayConverter[] int_to_bitarr_converter.set_bitstring_cache[ {key: format[key, 'b'] for key in range[CACHE_SIZE]}] with Pool[] as pool: ndarray_bitarr_ls = pool.map[ int_to_bitarr_converter.convert, [random.randint[0, CACHE_SIZE - 1] for _ in range[ITER_SIZE]]]]
0CACHE_SIZE = 1024 * 1024 # 1 MB ITER_SIZE = 1000000 # 1 million int_to_bitarr_converter = IntToBitarrayConverter[] int_to_bitarr_converter.set_bitstring_cache[ {key: format[key, 'b'] for key in range[CACHE_SIZE]}] with Pool[] as pool: ndarray_bitarr_ls = pool.map[ int_to_bitarr_converter.convert, [random.randint[0, CACHE_SIZE - 1] for _ in range[ITER_SIZE]]]]
6 trở thành mộtCACHE_SIZE = 1024 * 1024 # 1 MB ITER_SIZE = 1000000 # 1 million int_to_bitarr_converter = IntToBitarrayConverter[] int_to_bitarr_converter.set_bitstring_cache[ {key: format[key, 'b'] for key in range[CACHE_SIZE]}] with Pool[] as pool: ndarray_bitarr_ls = pool.map[ int_to_bitarr_converter.convert, [random.randint[0, CACHE_SIZE - 1] for _ in range[ITER_SIZE]]]]
0CACHE_SIZE = 1024 * 1024 # 1 MB ITER_SIZE = 1000000 # 1 million int_to_bitarr_converter = IntToBitarrayConverter[] int_to_bitarr_converter.set_bitstring_cache[ {key: format[key, 'b'] for key in range[CACHE_SIZE]}] with Pool[] as pool: ndarray_bitarr_ls = pool.map[ int_to_bitarr_converter.convert, [random.randint[0, CACHE_SIZE - 1] for _ in range[ITER_SIZE]]]]
Ghi chú. Những gì chúng tôi đã làm ở đây về cơ bản là gói 2 hàm toàn cục, với 1 biến toàn cục và cùng định vị chúng trong cùng một
8. Điều này đang lặng lẽ tiếp cận mô hình chống đơn lẻ, nhưng tôi thích sự đóng gói ở đây hơn toàn cầu, mặc dù nó là một mặt tiền nguy hiểm…CACHE_SIZE = 1024 * 1024 # 1 MB ITER_SIZE = 1000000 # 1 million int_to_bitarr_converter = IntToBitarrayConverter[] int_to_bitarr_converter.set_bitstring_cache[ {key: format[key, 'b'] for key in range[CACHE_SIZE]}] with Pool[] as pool: ndarray_bitarr_ls = pool.map[ int_to_bitarr_converter.convert, [random.randint[0, CACHE_SIZE - 1] for _ in range[ITER_SIZE]]]]
Bây giờ, khi chúng tôi chạy mã song song ở trên, vì
CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
9 và class ClassMethodBitarrayConverter[IntToBitarrayConverter]:
bitstring_cache = None
@classmethod
def set_bitstring_cache[cls, bitstring_cache: Dict]:
cls.bitstring_cache = bitstring_cache
@classmethod
def convert[cls, integer: int, init_return=None] -> np.ndarray:
bitstring = cls.bitstring_cache[integer]
return cls._bitstring_to_ndarray[bitstring]
0 là các toàn cầu được tôn vinh, nên CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
0 có quyền truy cập vào CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
3, mà không cần bất kỳ yêu cầu tuần tự hóa/giải tuần tự hóa nào, trong mỗi Quy trình class ClassMethodBitarrayConverter[IntToBitarrayConverter]:
bitstring_cache = None
@classmethod
def set_bitstring_cache[cls, bitstring_cache: Dict]:
cls.bitstring_cache = bitstring_cache
@classmethod
def convert[cls, integer: int, init_return=None] -> np.ndarray:
bitstring = cls.bitstring_cache[integer]
return cls._bitstring_to_ndarray[bitstring]
3So với 32. 5s trong lần triển khai trước đây của chúng tôi, giải pháp toàn cầu cao cấp của chúng tôi chỉ chạy trong 5s
Ghi chú. Nếu bạn đã , bạn sẽ nhận thấy rằng đây là hiệu suất tương tự như mã tuần tự, không song song của chúng tôi. Điều này là do phương pháp
0 không sử dụng nhiều CPU. Đây là một chủ đề cho một bài viết khácCACHE_SIZE = 1024 * 1024 # 1 MB ITER_SIZE = 1000000 # 1 million int_to_bitarr_converter = IntToBitarrayConverter[] int_to_bitarr_converter.set_bitstring_cache[ {key: format[key, 'b'] for key in range[CACHE_SIZE]}] with Pool[] as pool: ndarray_bitarr_ls = pool.map[ int_to_bitarr_converter.convert, [random.randint[0, CACHE_SIZE - 1] for _ in range[ITER_SIZE]]]]
Chúng tôi thấy trong các cuộc gọi được định hình tới
class ClassMethodBitarrayConverter[IntToBitarrayConverter]:
bitstring_cache = None
@classmethod
def set_bitstring_cache[cls, bitstring_cache: Dict]:
cls.bitstring_cache = bitstring_cache
@classmethod
def convert[cls, integer: int, init_return=None] -> np.ndarray:
bitstring = cls.bitstring_cache[integer]
return cls._bitstring_to_ndarray[bitstring]
5 và class ClassMethodBitarrayConverter[IntToBitarrayConverter]:
bitstring_cache = None
@classmethod
def set_bitstring_cache[cls, bitstring_cache: Dict]:
cls.bitstring_cache = bitstring_cache
@classmethod
def convert[cls, integer: int, init_return=None] -> np.ndarray:
bitstring = cls.bitstring_cache[integer]
return cls._bitstring_to_ndarray[bitstring]
6Processdumps[] calldumps[] time[s]avgloads[] callloads[] time[s]avgParent424. 09s. 09s337. 36s. 13s1410. 34s2. 57s5. 04s. 008s2410. 31s2. 57s5. 04s. 008s3410. 31s2. 57s5. 04s. 008s4410. 36s2. 58s5. 04s. 008s5410. 23s2. 55s5. 04s. 008s6410. 19s2. 54s5. 04s. 008s7410. 04s2. 52s5. 04s. 008s849. 88s2. 47s5. 04s. 008sGiảm thiểu mối quan tâm toàn cầu
Triển khai mới của chúng tôi ở trên được gói gọn trong một lớp, đó là một Lập trình hướng đối tượng đảm nhận toàn cầu. Tuy nhiên, theo ý kiến của tôi, nó rõ ràng hơn là xác định biến toàn cục trong phạm vi lồng nhau, như một số bài đăng đề xuất
Các thuộc tính của lớp vẫn là các biến toàn cục, nhưng ít nhất chúng được gói gọn ở một mức độ nào đó và chỉ có sẵn dưới dạng các thuộc tính trên lớp, so với. bất cứ nơi nào. Điều này sẽ trả cổ tức khi cố gắng gỡ lỗi và duy trì cơ sở mã này, vì chỉ các mô-đun phụ thuộc vào lớp này mới cố gắng truy cập vào biến này
Đề xuất phi toàn cầu
Bất chấp những lời chỉ trích của tôi về toàn cầu đối với trường hợp sử dụng cụ thể này, câu hỏi “liệu toàn cầu có xấu không” không có câu trả lời rõ ràng và phụ thuộc vào ngữ cảnh sử dụng. Mọi người cũng rất có ý kiến về chủ đề này. xem bài SO này
Điều đó nói rằng, lời chỉ trích của tôi là người dùng Python không nên bị buộc phải sử dụng toàn cục hoặc thậm chí là từ khóa
class ClassMethodBitarrayConverter[IntToBitarrayConverter]:
bitstring_cache = None
@classmethod
def set_bitstring_cache[cls, bitstring_cache: Dict]:
cls.bitstring_cache = bitstring_cache
@classmethod
def convert[cls, integer: int, init_return=None] -> np.ndarray:
bitstring = cls.bitstring_cache[integer]
return cls._bitstring_to_ndarray[bitstring]
7 để sử dụng API CACHE_SIZE = 1024 * 1024 # 1 MB
ITER_SIZE = 1000000 # 1 million
int_to_bitarr_converter = IntToBitarrayConverter[]
int_to_bitarr_converter.set_bitstring_cache[
{key: format[key, 'b'] for key in range[CACHE_SIZE]}]
with Pool[] as pool:
ndarray_bitarr_ls = pool.map[
int_to_bitarr_converter.convert,
[random.randint[0, CACHE_SIZE - 1]
for _ in range[ITER_SIZE]]]]
1Tôi đã đề xuất một tiện ích mở rộng đã được thử nghiệm tốt, tương thích ngược của API
class ClassMethodBitarrayConverter[IntToBitarrayConverter]:
bitstring_cache = None
@classmethod
def set_bitstring_cache[cls, bitstring_cache: Dict]:
cls.bitstring_cache = bitstring_cache
@classmethod
def convert[cls, integer: int, init_return=None] -> np.ndarray:
bitstring = cls.bitstring_cache[integer]
return cls._bitstring_to_ndarray[bitstring]
9 cho phép giải pháp phi toàn cầu cho vấn đề truyền dữ liệu tới và khởi tạo các quy trình của Pool worker