由于您正在分配连续的块,您应该能够执行以下操作(完全摆脱内部循环):

for _ in xrange(0, num_flushes):
in_memory_blocks[:blocks_per_flush] = numpy.random.randint(
0, _BLOCK_MAX+1, blocks_per_flush)
print('flushing bytes stored in memory...')
# commented out for SO; exists in actual code
# removing this doesn't make an order-of-magnitude difference in time
# m.update(in_memory_blocks[:blocks_per_flush])
in_memory_blocks[:blocks_per_flush].tofile(f)

这使用numpy.random.randint函数,该函数分配整个内存块并用随机整数填充(注意J.F.Sebastian关于numpy.random.randint与random.randint的评论。使用numpy随机例程填充预分配的数组是没有办法(据我所知)。另一个问题是numpy的randint返回int64数组。如果你需要一些其他大小的整数,那么你可以使用numpy类型方法,例如numpy.uint8。如果你想要randints覆盖整个类型的范围,那么下面使用numpy.random.bytes的@J. F. Sebastian方法将是最好的(几乎在任何情况下都是如此!)。

然而,简单测试显示合理的时间(与C代码的数量级相同)。以下代码使用numpy方法测试分配20,000个随机整数的uint8数组的时间:

from timeit import Timer
t = Timer(stmt='a=numpy.uint8(numpy.random.randint(0, 100, 20000000))',
setup='import numpy')
test_runs = 50
time = t.timeit(test_runs)/test_runs
print time

我在我4岁的Core2笔记本电脑上每次分配大约需要0.7秒(它运行50次,因此运行整个测试需要更长的时间)。这是每次分配20,000,000个随机uint8整数的0.7秒,所以我希望整个500MB大约20秒左右。

更多内存意味着您可以同时分配更大的块,但是当您只需要8时,您仍然有效地浪费时间为每个int分配和写入64位(我没有量化此效果)。如果它仍然不够快,你可以使用numpy ctypes接口调用你的C实现。这真的很容易使用,你几乎没有比纯C慢。

一般的回家消息是,numpy总是尝试使用它们存在的numpy例程,记住用ctypes回退到C并不是太痛苦。一般来说,这种方法可以非常有效地使用python,而且数值处理的速度很慢。

编辑:我刚刚遇到的其他事情:正如上面所实现的那样,我认为你会制作一个额外的不必要副本。如果in_memory_blocks长度为blocks_per_flush,那么您最好只为其分配numpy.random.randint的返回值,而不是将其分配给某个子数组(在一般情况下为必须是副本)。所以:

in_memory_blocks = numpy.random.randint(0, _BLOCK_MAX+1, blocks_per_flush)

而不是:

in_memory_blocks[:blocks_per_flush] = numpy.random.randint(
0, _BLOCK_MAX+1, blocks_per_flush)

然而,考虑到时间,第一种情况并没有导致速度显着提高(仅约2%),因此可能不值得担心太多。我想绝大部分时间花在实际生成随机数上(这是我所期望的)。