Question

Just wondering if anyone can help me with a little programming math i'm having trouble with.

What I am trying to create is a submit script (using python and .bat) for Nuke (vfx). The issue I am having is I can't figure out how to add the remainder of frames to the already calculated stack.

To be more clear...

In Nuke, i have to render 20 frames. I have 16 threads. Nuke only uses 1 thread. I want to write a script that takes the number of frames and divide it by the number of threads and write out a bat file using python. The issue come is when I have a remainder. I want to take the remainder and apply it back in the render stack.

example (first loop)

thread1 = 1 frame
thread2 = 1 frame
thread3 = 1 frame
thread4 = 1 frame
thread5 = 1 frame
thread6 = 1 frame
...
thread16 = 1 frame

Once it has done this...the remainder is 4. I want the remainder to be distributed among the threads. so...

example (second loops)

thread1 = 2 frame
thread2 = 2 frame
thread3 = 2 frame
thread4 = 2 frame
thread5 = 1 frame
thread6 = 1 frame
...
thread16 = 1 frame

the 4 gets added among the first few threads totalling 20 frames.

I will greatly appreciate any help, tips, comments that anyone has to offer. :)

Thanks

Was it helpful?

Solution

frames can be a list of any object, eg dict or "Frame" object. Here I have just used ints

>>> frames = range(20)
>>> threads = 16
>>> [frames[x::threads] for x in range(threads)]
[[0, 16], [1, 17], [2, 18], [3, 19], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15]]

I think you may be better off putting the frames in a Queue though, since some frames may render faster than others

OTHER TIPS

This is a classic use of the Bresenham algorithm:

def partition(lst, n):
    increment = len(lst) / float(n)
    last = 0
    i = 1
    results = []
    while last < len(lst):
        idx = int(round(increment * i))
        results.append(lst[last:idx])
        last = idx
        i += 1
    return results


for i, frames in enumerate(partition(range(20),16)):
    if len(frames)>1:
        print 'thread'+str(i+1),'=', len(frames),'frames'
    else:
        print 'thread'+str(i+1),'=', len(frames),'frame'

The partition bit is from this answer.

It prints:

thread1 = 1 frame
thread2 = 2 frames
thread3 = 1 frame
thread4 = 1 frame
thread5 = 1 frame
thread6 = 2 frames
thread7 = 1 frame
thread8 = 1 frame
thread9 = 1 frame
thread10 = 2 frames
thread11 = 1 frame
thread12 = 1 frame
thread13 = 1 frame
thread14 = 2 frames
thread15 = 1 frame
thread16 = 1 frame

You could also use Mark Dickinson's solution if you don't mind the two frame threads being front loaded.

Then you have:

def partition(lst, n):
    q, r = divmod(len(lst), n)
    indices = [q*i + min(i, r) for i in xrange(n+1)]
    return [lst[indices[i]:indices[i+1]] for i in xrange(n)]

which prints:

thread1 = 2 frames
thread2 = 2 frames
thread3 = 2 frames
thread4 = 2 frames
thread5 = 1 frame
thread6 = 1 frame
thread7 = 1 frame
thread8 = 1 frame
thread9 = 1 frame
thread10 = 1 frame
thread11 = 1 frame
thread12 = 1 frame
thread13 = 1 frame
thread14 = 1 frame
thread15 = 1 frame
thread16 = 1 frame
frames=20
tPos=16
Ts=divmod(frames,tPos)
threads=[Ts[0]+1 if i < Ts[1] else Ts[0] for i in range(tPos)]

>>> threads    
>>> [2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

If you are having trouble with list comprehensions, the same thing can be written this way:

threads=[]
for i in range(tPos):
    threads.append(Ts[0]+1 if i<Ts[1] else Ts[0])

Then to format it, do something like:

for i,e in enumerate(threads):
    print 'thread{} {}frames'.format(i,e)

This is what I ended up using....Thanks for you help everyone.

frames=20 
tPos=16 
Ts=divmod(frames,tPos) 
threads=[] 
for i in range(tPos): 
    threads.append(Ts[0]+1 if i<Ts[1] else Ts[0])

start = 1
end = 0
x=1
while x <= (tPos):
    end = start +(threads[x-1]-1)
    print (start, "-", end)
    start = end + 1
    x+=1


prints:
1 - 2
3 - 4
5 - 6
7 - 8
9 - 9
10 - 10
11 - 11
12 - 12
13 - 13
14 - 14
15 - 15
16 - 16
17 - 17
18 - 18
19 - 19
20 - 20
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top