I'm trying to solve optimization problem for many many periods. I'm thinking about using multiple threads, do I need to write each thread one by one? Is there any easy way to write them? For example, can I write it in some way kind of like loop?
The best way to solve the same optimization problem with different input data is to wrap all of the code except the loading and splitting up of data into a procedure. Then you will have to create the separate threads, but you will only need to pass them one procedure call instead of lines and lines of code.
For example if you are using COMT and you want to solve an optimization problem over 2 periods and each period is 120 observations you will want to do something like this:
//load data for all periods load depvar; load indvar; //number of optimization problems num_periods = 2; //declare your output structure struct comtResults out; //reshape output structure to num_periods by 1 array out = reshape(out, num_periods, 1); threadStat out = callCOMT(depvar[1:120], indvar[1:120, .]); threadStat out = callCOMT(depvar[121:240], indvar[120:240,.]); threadJoin; proc (1) = callCOMT(depvar, indvar); //Declare and fill in: // PV structs, DS structs, Control structures //Call COMT //return the COMT results structure endp;
Most of the code you need to write will be inside of the callCOMT procedure. You will only have to write this once with no duplication since it can be used by each thread. The only duplication will be on the threadStat lines which is minimal.
One more thing to remember is that since you are running multiple optimization problems each inside of a separate thread, you will want to turn off threading inside of the optimization procedure by setting the useThreads member of the control structure to 0. This will prevent your code from creating more threads than your computer can effectively process.
Thanks a lot for your prompt reply.
I have one more question about the threading inside the optimization procedure. If I don't turn off the thread and the code creates more threads, what would be the consequences? Will it slow down the code? Lead to wrong output?
The consequences for leaving the threading on inside of the optimization procedure will be that you will likely create many more threads than you have cores on your machine which will "oversubscribe" the CPU. It will also use quite a bit more memory. So on most machines, it would slow down the code. It safe, however, you should not have any risk of wrong output.
Usually how many threads with the threading inside the optimization procedure creates? Is it random? Does it depend on the specific problem it is solving?
Typically between 4 and 8 threads will be created inside of the optimization procedures with threading turned on.
I see. Thanks a lot.
In terms of proc call COMT, I cannot assign to any global variable inside the procedure, can I?
You cannot assign to the same global value inside of ANY procedure that is called from inside of more than 1 thread. This will cause your program to crash. However, you can assign to different portions of a global matrix. For example, this is legal:
x = zeros(2, 1); threadStat x = 1; threadStat x = 2; threadJoin;
However, you must make certain that each element of the matrix will ONLY be updated by 1 thread. If more than one thread assigns to the same location, you program may crash and/or you may get incorrect or inconsistent results. Which of these happens will depend upon the order in which the threads complete their work.
Many thanks for your prompt reply. This is very helpful.
I have one last question about proc callCOMT. Inside the procedure, I need to define
PV structs, DS structs, Control structures. For example, struct DS d1; d1=dsCreate; d1.datamatrix=depvar; struct PV p1; p1=PVCreate; p1=pvPack(p1,cpqs,"x");
Are d1, d1.datamatrix and p1 local variables?
When I list local variables at the beginning of the procedure, should I include them?
You have a lot of options for how you set this up. I think I would probably set up the PV struct and DS structures as global variables and then pass them into my callCOMT function.
If they had the same starting values, then I would set up one instance of the structure and pass that same structure instance into each of the callCOMT procedures. Once a variable has been passed into a procedure, it will exist as a local variable inside that procedure.
If the structure had different values for each thread, then I would create an array of structures and pass in a subset of this array to the corresponding call to callCOMT.
Here is a simplified example (only using the DS structure for simplicity) where I want to pass in the same data to each call of callCOMT:
//load dependent variable load y; //declare and instantiate DS structure struct DS d; d = dsCreate(); d.dataMatrix = y; threadStat callCOMT(d); threadStat callCOMT(d); threadJoin;
Here is the equivalent example using an array of DS structures to pass part of 'y' to each callCOMT:
//load dependent variable load y; //declare and instantiate DS structure struct DS d; d = dsCreate(); //reshape into 2x1 array of structures d = reshape(d, 2, 1); //Assign portions of 'y' d.dataMatrix = y[1:100]; d.dataMatrix = y[101:200]; threadStat callCOMT(d); threadStat callCOMT(d); threadJoin;
Thanks a lot for your reply.
Can I do similar thing to comtControl? For example,
struct comtControl c11; c11=comtControlCreate(); c11=reshape(c11,2,1); c11.A=a1; c11.B=b1; c11.A=a2; c11.B=b2; threadStat callCOMT(d,c11); threadStat callCOMT(d,c11); threadJoin;
Is this correct? Thanks.
Yes, that will work.