How magical is snowfall? Specially in the hands of the playful wind!
How many particles are in that particle system? How detailed is the noise function that generates such coherent, yet chaotic behavior? How fast is the memory bus that allows so much geometry to be processed per frame! And since there are many observers, it can’t be implemented as an image-based effect. All the polygons must be generated, and you can’t reuse the index buffers. Also, alpha rejection is not used, because I saw no jagged edges. And the textures were so detailed. How is it that they don’t run into memory bandwidth issues? And every single billboard is lit and shaded correctly! How many shader pipelines do they have?
Printer-friendly version
ahf | 07-Jan-08 at 8:53 am | Permalink
http://www.kurzweilai.net/meme/frame.html?main=/articles/art0530.html
Seyed Amin Mirzaei | 09-Jan-08 at 11:17 pm | Permalink
Shader? I think there’s no need for that in their system. Every entity (or even every particle?) in the system has its own GPU, and only one of many things done in each loop is to call their render() function! (or maybe it’s a true multi-threaded environment? (or even multi-processor, or another unknown technology…))
However, what do you think about the resolution of our screens?!
yzt | 10-Jan-08 at 11:30 pm | Permalink
The system you describe is only good for one viewer! The loop
) can possibly only work for one viewer. Am I mistaken? Wouldn’t we need a O(n2) worst-case loop to render each particle with respect to each observer?
for x in particles: x.render()
or (if you prefer a more parallel-o-phil version)
for (ParticleContainer::iterator pi = particles.begin(); pi != particles.end(); ++pi)
if (!fork()) pi->render();
(that was good, wasn’t it?
I always thought the universe is more like a message-passing system, with photons, neutrinos, gluons, etc. being the messages and the (more) massive particles the processors (or nodes or agents or whatever your creed makes you call them!) This too would require a O(n2) algorithm.
Of course, divide-and-conquer methods may be applicable (Binary Space-Time Partitioning? Hexadecatrees?) to reduce it to O(n lg n)!
MatGill | 11-Jan-08 at 9:07 pm | Permalink
From and old piece of code, multiple shells with IPC kinda stuff. Look, I wrote that if in the full form, but it’s much more clear to understand right now. And the cool thing is that I used STL all over the place.
…
for (int i = 0; i < n; i++)
if ((pID[i] = fork())==0) {
ostringstream idArg;
idArg << i;
….
execlp(”./shell”, “shell”, idArg.str().c_str(), maxIDArg.str().c_str(), segmentIDArg.str().c_str(), 0);
/* shouldn’t get here */
cout << “Akhe Chera? ha chera?” << endl;
break;
return 0;
}
int st;
while(n–)
wait(&st);
}
…
Yeah, good old days …
MatGill | 11-Jan-08 at 9:41 pm | Permalink
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
#include “sleep.h”
int main(int argc, char** argv) {
if (argc<2) {
cout << “Number of shells
should be passed as an argument.” << endl;
return 1;
}
int n;
istringstream arg(argv[1]);
if (!(arg >> n)) {
cout << “A number should be
passed as the argument.” << endl;
return 1;
}
cout << “Forking ” << n << ”
shells…” << endl;
const int sharedSegmentSize = 0×6400;
int segmentID = shmget(IPC_PRIVATE,
sharedSegmentSize, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
char* sharedMemory = (char*) shmat(segmentID, 0, 0);
pid_t* pID = (pid_t*)sharedMemory;
for (int i = 0; i < n; i++)
if ((pID[i] = fork())==0) {
ostringstream
idArg;
idArg <<
i;
ostringstream
maxIDArg;
maxIDArg
<< n;
ostringstream
segmentIDArg;
segmentIDArg
<< segmentID;
execlp(”./shell”, “shell”, idArg.str().c_str(), maxIDArg.str().c_str(),
segmentIDArg.str().c_str(), 0);
cout <<
“Akhe Chera? ha chera?” << endl;
break;
return 0;
}
// cout << sleep() << endl;
int st;
while(n–)
wait(&st);
shmctl (segmentID, IPC_RMID, 0);
}
yzt | 13-Jan-08 at 2:03 pm | Permalink
I didn’t really get the relevance, but thanks for sharing anyway!
By the way, isn’t there a race condition present in the above code? When you write the PIDs to the allocated shared memory, you do it like this: pID[i] = fork() (where pID points to the start of the shared memory block and we assume it has enough room.) The previous statement seems dependant on the order of execution of the two processes after the fork() call. If I understand correctly, the pID array is supposed to hold the PIDs of the children so you can wait() on them, isn’t it? (BTW, is that wait() call alright?) Therefore, if the child writes its PID in there, and then the parent overwrites it with zero, we lose that child’s ID, won’t we?
MatGill | 14-Jan-08 at 4:15 am | Permalink
Well, you don’t need pids to wait. pids where used only as ids to communicate using the shared memory. So that you’d put a message there from and id to another id (using some mutex I think).
And about that race condition you mentioned with putting the pids, I don’t think so. The parent process is putting in the pid values and the child processes don’t modify it, AFAICR. I don’t really remember the code for “shell”, but I think each one waited until all others where initialized and the ids where stored.
Anyway, that’s a long time ago, and it’s not relevant. Just wanted to post some code to check it on WordPress. Try installing the plugin that allows “code” tags.
MatGill | 14-Jan-08 at 4:17 am | Permalink
I _am_ getting old!
yzt | 14-Jan-08 at 12:00 pm | Permalink
OK, so forget about PIDs for waiting. But about fork(), I the fork system call is called once but it actually returns twice: once to the parent process returning the PID of the child and once to the child returning 0. Now, when the parent process forks off, suppose that the child is not given the CPU and the parent gets to write the PID it got from fork into the shared memory. Now the child executes exactly the same code but writes 0 to the exact same spot. That’s bad I think.
But you’re right. I do need a code formatting plug-in!
MatGill | 14-Jan-08 at 5:11 pm | Permalink
Gee! I got your point.
Should have been something like:
if (!(cID = fork()) | !(pID[i] = cID))
But I wonder why it works. You always think stochastic when it comes to multi tasking. But maybe when you fork a process it is given the CPU right after that. Of course that might be different on different platforms.
yzt | 14-Jan-08 at 11:59 pm | Permalink
Gee, you are getting old, friend!

You have to put a “&&” in the condition! But wouldn’t it just be easier, more readable and even prettier to say:
cID = fork();
if (0 != cID) pID[i] = cID;
else {…}
What are your thoughts on C/C++ wizardry versus readability? (think a ^= b ^= a ^= b; versus swap(a, b);!) I used to love constructs like the former, but I’ve come to realize the former is dangerous even if it wasn’t potentially incorrect and actually longer in this example. I guess either I’m more experienced and more skillful now, or I’m just older and less sharp!
MatGill | 15-Jan-08 at 1:18 am | Permalink
No, I’m afraid you are wrong about the “&&” point. You also don’t need a “logical or”, a bitwise one would suffice. Maybe the point is that the your “else block” is my “then block”.
And about the point of readability, as I told you in few comments ago, I try to have my code as readable as possible. That’s practically obvious in my posted code.
“const int sharedSegmentSize;”
“if ((pID[i] = fork())==0)”
“ostringstream segmentIDArg;”
“segmentIDArg << segmentID;”
And you know, I make heavy use of standard libraries all the time. Makes the code much more readable and maintainable. The above code, for instance, could have been done with sprintf type of stuff, which I really hate. They belong to people like Eric Raymond, who prefer to code in C when it’s absolutely irrelevant.
Still when it came to coding for programming contests, I used to do a lot of tricks to make coding faster. So the code was only readable to me (and hopefully my teammates).
Anyway, if you had to code in Matlab, then you’d know that life is not really that easy. Feels like Fortran. And you know, Gods hate Fortran. Poor me!
yzt | 15-Jan-08 at 1:20 pm | Permalink
I do know that you can use bitwise OR in place of logical OR (when you’re sure the 1-bits are at the same location, like in this case that you have used logical NOT to make sure of that) but logical OR can be faster for two reasons: it’s more super-scalar friendly (I think!) and more importantly it has “short-circuit” behavior. I’m sure you know this already, but for the benefit of our spectators(!) let me explain. In a C/C++ logical expression, the evaluation is done only up to the point that the result becomes clear. That means if you have A || B and A turns out to be true, B is never evaluated. This is particularly important if B has side effects (e.g. in ++a || ++b assuming a and b are integers, b is never incremented unless a is equal to -1.)
I don’t think bitwise operations have this short-circuit feature.
So, in your bitwise OR expression, both the assignments are always carried out, which means the cID always gets assigned to pID[i] which nullifies the point.
However, if you write the condition like this:
if (!((cID = fork()) && (pID[i] = cID)))
it would be functionally equivalent to what you wrote (i.e. it only enters the “then” block when executing the child) except that it won’t write to the pID vector in the child process, because of the logical AND short-circuiting out.
yzt | 15-Jan-08 at 1:22 pm | Permalink
MATLAB?! Poor you! I guess I’m lucky no one forces me to write anything in something other than C++, Cg and Python!
The only way anyone could separate me from C++ would be to pry it from my cold dead fingers, or offering enough money!
MatGill | 15-Jan-08 at 4:22 pm | Permalink
Just for the sake of the interested spectator(s), when it gets to a single bit (booleans), bitwise works just in the same way. It is actually converted to logical (it doesn’t really matter, in fact bitwise on booleans is supposed to be logical). So your concerns (both about the speed and short-cutting) are not valid.
I tried using open-source clones of Matlab. They are way slower! Damn it!
yzt | 17-Jan-08 at 12:34 am | Permalink
As a side note, a friend of mine sent me this link. If you are into snowflakes and ice, this is your site!