占位符python
I am ashamed to tell you to how many figures I carried these calculations [of Pi], having no other business at that time
我很ham愧,告诉你我当时进行了多少次Pi计算,当时没有其他事务
-Isaac Newton
-艾萨克·牛顿
Quite often, we need to compare two machines or two architectures for computation speed. Sometimes, we need to estimate the maximum percentage time reduction possible by parallelizing a sequential process. Sometimes, we just need to run a computationally intensive task on a CPU or a thread, or, in other words, keep that CPU or thread busy. In such cases, we often need a placeholder function that is easy to implement, has the execution time in the required range, and is, depending on the computation, easy to parallelize. Turns out that what Newton did to keep himself busy, is also a very suitable task to keep your machine busy.
通常,我们需要比较两台机器或两种体系结构的计算速度。 有时,我们需要通过并行化顺序过程来估计最大可能的时间减少百分比。 有时,我们只需要在CPU或线程上运行计算量大的任务,或者换句话说,让该CPU或线程处于繁忙状态 。 在这种情况下,我们经常需要一个占位符函数,该函数易于实现,执行时间在所需范围内,并且取决于计算,因此易于并行化。 事实证明,牛顿所做的使自己忙碌的事情,也是使机器忙碌的非常合适的任务。
In this post, I’ll introduce my favorite function for all such computations. It is based on the Leibniz formula for Pi:
在这篇文章中,我将介绍我喜欢的用于所有此类计算的函数。 它基于Pi的Leibniz公式 :
Leibniz formula for Pi Pi的莱布尼兹公式As you can see, this is an infinite series, whose terms progressively get smaller. We harness this property to create a function that would accurately output the first n decimal places of Pi, n being the input.
如您所见,这是一个无限级数,其项逐渐变小。 我们利用此属性来创建一个函数,该函数可以精确输出Pi的前n个小数位,n为输入。
def get_pi_n_decimals(n): pi_by_4 = 0 max_denominator = 10**(n+3) max_iter = int((max_denominator-1)/2) #denominator = 2*iter+1 for i in range(max_iter): pi_by_4 += ((-1)**i)*(1/(2*i+1))*(10**(n+3)) return int(pi_by_4 * 4/1000)The underlying idea is that a term like 1/10001 will have very little impact on the first decimal place. Given n, we compute the terms of the series till we reach a denominator of 10^(n+3) . The terms after that won’t affect the nth decimal place significantly, if at all. We return an integer containing all the first n decimal places of Pi.
基本思想是,像1/10001这样的术语对小数点后第一位的影响很小。 给定n,我们计算序列的项,直到分母达到10^(n+3)为止。 如果有的话,后面的术语将不会显着影响小数点后第n位。 我们返回一个整数,其中包含Pi的所有前n个小数位。
Here’s the output when this function is executed on my machine:
这是在我的机器上执行此功能时的输出:
Several salient features make this function ideal as a placeholder for computation benchmarking. I’ll list them one by one.
几个突出的功能使该功能非常适合作为计算基准测试的占位符。 我会一一列出。
If you pay close attention, the execution time increases by an order of magnitude with a unit increase in n. On my machine, the execution time in milliseconds has as many digits as n, at least for the first few iterations. That makes this very useful. Have a constraint on the time for which the function should execute? Just set n accordingly. It doesn’t matter if you have an ultra-high-speed supercomputer or a single-core machine with Intel Pentium. You can always find an ideal n.
如果密切注意,执行时间将增加一个数量级,单位为n。 在我的机器上,至少在前几次迭代中,执行时间(以毫秒为单位)与n一样多。 这使它非常有用。 对函数执行的时间有约束吗? 只需相应地设置n。 您是否拥有配备Intel Pentium的超高速超级计算机或单核计算机都没有关系。 您总能找到理想的n。
Because this function contains a for loop, it is very easy to parallelize. We can simply split the iterable in different chunks, and use the chunks as inputs. An example using processes is shown below:
由于此函数包含一个for循环,因此很容易并行化。 我们可以简单地将迭代器拆分为不同的块,然后将这些块用作输入。 使用流程的示例如下所示:
from multiprocessing import Process, Pipedef get_pi_subrange(n,subrange,conn): pi_by_4 = 0 for i in subrange: pi_by_4 += ((-1)**i)*(1/(2*i+1))*(10**(n+3)) conn.send([int(pi_by_4 * 4)]) conn.close()def get_pi_n_decimals_par(n, n_chunks): max_denominator = 10**(n+3) max_i = int((max_denominator-1)/2) ranges = [] for i in range(n_chunks): r_i = range(int(i*max_i/n_chunks),int((i+1)*max_i/n_chunks)) ranges.append(r_i) # create a list to keep all processes processes = [] # create a list to keep connections parent_connections = [] for subrange in ranges: #This loop can be parallelized parent_conn, child_conn = Pipe() parent_connections.append(parent_conn) process = Process(target=get_pi_subrange, args=(n, subrange, child_conn,)) processes.append(process) # start all processes for process in processes: process.start() # make sure that all processes have finished for process in processes: process.join() ans = 0 for parent_connection in parent_connections: ans += parent_connection.recv()[0] return int(ans/1000)This function is completely CPU-intensive. The execution time is the computation time.
此功能完全占用CPU。 执行时间是计算时间。
The function successively adds the output of each loop to the final answer. This ensures that the memory usage remains limited. What also helps is that each successive term keeps getting smaller and smaller in magnitude.
该函数依次将每个循环的输出添加到最终答案。 这样可以确保内存使用率保持受限。 还有一个帮助是,每个连续项的大小越来越小。
You don’t need to import any extra libraries like NumPy. You can run this directly if you have python installed. This avoids extra variables in the benchmarking process, like the availability of the library in the machine, its version, etc.
您不需要导入任何其他库,例如NumPy。 如果您已安装python,则可以直接运行此程序。 这样可以避免在基准测试过程中产生额外的变量,例如机器中库的可用性,版本等。
Though this is a placeholder function, there is some directed computation happening. And the output is a universally known mathematical constant, Pi. So it is easy to verify whether the computation was executed without any errors or not.
尽管这是一个占位符函数,但还是发生了一些定向计算。 输出是一个众所周知的数学常数Pi。 因此,很容易验证计算是否正确执行。
This function, given the Leibniz formula, can easily be understood and translated in other languages, like C, Java, etc. Of course, you will have to respect the language-specific constraints, like the maximum value of an integer in that language and so on.
给出了Leibniz公式后,此函数可以轻松理解和翻译为其他语言,例如C,Java等。当然,您必须遵守特定于语言的约束,例如该语言中整数的最大值和以此类推。
Pi is beautiful. And useful. And convenient. And …
皮很漂亮 而且有用。 又方便。 还有...
Just like Pi, I can go on and on. But coming back to the function, it proves to be ideal for several use-cases. It has several of the attributes, if not all, that you would want a placeholder function to have. It is flexible and scalable, and quite easy to understand, remember, and implement. So go ahead and use this function whenever you need to perform some comparisons or when you just want to keep the machine or a thread busy.
就像Pi一样,我可以继续下去。 但是回到功能上,它被证明是几个用例的理想选择。 它具有一些您需要占位符功能的属性(如果不是全部)。 它具有灵活性和可扩展性,并且非常易于理解,记住和实施。 因此,只要需要执行一些比较或仅想让机器或线程保持繁忙,就继续使用此功能。
翻译自: https://medium.com/analytics-vidhya/the-perfect-placeholder-function-for-python-f907d31f529
占位符python