将十六进制值流转换为 16 位整数
Convert stream of hex values to 16-bit ints
我得到了大小为 61440 的十六进制值的二进制字符串包,类似于:
b'004702AF42324fe380ac...'
我需要将它们分成 4 个批次并将它们转换为整数。 16 位将是首选,但稍后投射这不是问题。我这样做的方式看起来像这样并且有效。
out = [int(img[i][j:j+4],16) for j in range(0,len(img[i]), 4)]
我遇到的问题是性能。事情是我每秒至少能得到 200 个,如果没有多线程,我每秒只能通过 100-150 个。
我可以通过某种方式提高速度吗?
我不认为多线程在这种情况下会有帮助,因为它纯粹是 CPU 密集型。将其分解为 4 个线程的开销将超过任何理论上的优势。尽管我不清楚为什么 img 似乎具有多个维度,但您的列表理解似乎尽可能高效。我已经编写了以下模拟,并且在我的机器上它始终在 ~0.8 秒内执行。我认为您从代码中获得的性能将在很大程度上取决于您的 CPU 的能力。这是代码:-
import random
from datetime import datetime
hv = '0123456789abcdef'
img = ''.join(random.choice(hv) for _ in range(61440))
start = datetime.now()
for _ in range(200):
out = [int(img[j:j + 4], 16) for j in range(0, len(img), 4)]
print(f'Duration={datetime.now()-start}')
这是对我早期产品的重写,展示了多线程实际上如何产生非常显着的差异 - 可能取决于系统架构。
以下代码在我的机器上执行时间约为 0.05 秒:-
import random
from datetime import datetime
import concurrent.futures
N = 10
R = 61440
IMG = []
for _ in range(N):
IMG.append(''.join(random.choice('0123456789abcdef')
for _ in range(R)))
"""
now IMG has N elements each containg R pseudo randomly generated hexadecimal values
"""
def tfunc(img, k):
return k, [int(img[j:j + 4], 16) for j in range(0, len(img), 4)]
R = [0] * N
start = datetime.now()
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = []
"""
note that we pass the relevant index to the worker function
because we can't be sure of the order of completion
"""
for i in range(N):
futures.append(executor.submit(tfunc, IMG[i], i))
for future in concurrent.futures.as_completed(futures):
k, r = future.result()
R[k] = r
"""
list R now contains the converted values from the same relative indexes in IMG
"""
print(f'Duration={datetime.now()-start}')
我做了更多的研究,发现我需要的不是多线程而是多进程。这使我从每秒 220 批次加速到每秒约 370 批次。现在这可能是其他地方的瓶颈,因为我在所有内核上只有 15% 的负载,但让我轻松地高于规格,这已经足够好了。
from multiprocessing import Pool
def combine(img):
return np.array([int(img[j:j+4],16) for j in range(0,len(img), 4)]).reshape((24,640))
p = Pool(20)
img = p.map(combine, tmp)
我得到了大小为 61440 的十六进制值的二进制字符串包,类似于:
b'004702AF42324fe380ac...'
我需要将它们分成 4 个批次并将它们转换为整数。 16 位将是首选,但稍后投射这不是问题。我这样做的方式看起来像这样并且有效。
out = [int(img[i][j:j+4],16) for j in range(0,len(img[i]), 4)]
我遇到的问题是性能。事情是我每秒至少能得到 200 个,如果没有多线程,我每秒只能通过 100-150 个。
我可以通过某种方式提高速度吗?
我不认为多线程在这种情况下会有帮助,因为它纯粹是 CPU 密集型。将其分解为 4 个线程的开销将超过任何理论上的优势。尽管我不清楚为什么 img 似乎具有多个维度,但您的列表理解似乎尽可能高效。我已经编写了以下模拟,并且在我的机器上它始终在 ~0.8 秒内执行。我认为您从代码中获得的性能将在很大程度上取决于您的 CPU 的能力。这是代码:-
import random
from datetime import datetime
hv = '0123456789abcdef'
img = ''.join(random.choice(hv) for _ in range(61440))
start = datetime.now()
for _ in range(200):
out = [int(img[j:j + 4], 16) for j in range(0, len(img), 4)]
print(f'Duration={datetime.now()-start}')
这是对我早期产品的重写,展示了多线程实际上如何产生非常显着的差异 - 可能取决于系统架构。
以下代码在我的机器上执行时间约为 0.05 秒:-
import random
from datetime import datetime
import concurrent.futures
N = 10
R = 61440
IMG = []
for _ in range(N):
IMG.append(''.join(random.choice('0123456789abcdef')
for _ in range(R)))
"""
now IMG has N elements each containg R pseudo randomly generated hexadecimal values
"""
def tfunc(img, k):
return k, [int(img[j:j + 4], 16) for j in range(0, len(img), 4)]
R = [0] * N
start = datetime.now()
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = []
"""
note that we pass the relevant index to the worker function
because we can't be sure of the order of completion
"""
for i in range(N):
futures.append(executor.submit(tfunc, IMG[i], i))
for future in concurrent.futures.as_completed(futures):
k, r = future.result()
R[k] = r
"""
list R now contains the converted values from the same relative indexes in IMG
"""
print(f'Duration={datetime.now()-start}')
我做了更多的研究,发现我需要的不是多线程而是多进程。这使我从每秒 220 批次加速到每秒约 370 批次。现在这可能是其他地方的瓶颈,因为我在所有内核上只有 15% 的负载,但让我轻松地高于规格,这已经足够好了。
from multiprocessing import Pool
def combine(img):
return np.array([int(img[j:j+4],16) for j in range(0,len(img), 4)]).reshape((24,640))
p = Pool(20)
img = p.map(combine, tmp)