www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to initialize an immutable array

reply "Sparsh Mittal" <sparsh0mittal gmail.com> writes:
I am making a program which accesses 1D array using for loop and 
then I am parallelizing this with foreach, TaskPool and parallel.

The array does not need to change, once initialized. However, the 
parallel version takes more time than serial version, which I 
think may be because compiler is trying to make sure that array 
is properly handled by different threads.

So, is there a way, an array can be made immutable and still 
initialized? Thanks a lot for your time.
Mar 01 2013
next sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
On Friday, 1 March 2013 at 20:05:41 UTC, Sparsh Mittal wrote:
 I am making a program which accesses 1D array using for loop 
 and then I am parallelizing this with foreach, TaskPool and 
 parallel.

 The array does not need to change, once initialized. However, 
 the parallel version takes more time than serial version, which 
 I think may be because compiler is trying to make sure that 
 array is properly handled by different threads.

 So, is there a way, an array can be made immutable and still 
 initialized? Thanks a lot for your time.
immutable arr = [ "some", "data", "that", "simple" ]; But I suppose your case is somewhat more complex. Probably you can provide an example of problem via DPaste (http://dpaste.1azy.net) ?
Mar 01 2013
parent reply "Sparsh Mittal" <sparsh0mittal gmail.com> writes:
Array is really big!


import std.stdio;
import std.datetime;
import std.parallelism;
import std.range;
//int numberOfWorkers = 2; //for parallel;
double my_abs(double n) { return n > 0 ? n : -n; }

immutable long DIM = 1024L*1024L *128L;

void main()
{

   double[] signal = new double[DIM+1];

   double temp;


   double sample[2]= [4.1,7.2];



   for(long i=0L; i< DIM+1; i++)
   {
     signal[i] = (i+ DIM)%7 + (i+DIM+1)%5; // could be any random 
value
   }

   //auto workerPool = new TaskPool(numberOfWorkers); // for 
parallel
   StopWatch sw;
   sw.start(); //start/resume mesuring.


   for (long i=0L; i< DIM; i++)
   //foreach(i; workerPool.parallel(iota(0, DIM))) // for parallel
   {

         temp =
         my_abs(sample[0]-signal[i]) + 
my_abs(sample[1]-signal[i+1]) ;
   }
   //workerPool.finish(); // for parallel

   sw.stop(); //stop/pause measuring.


   writeln(" Total time: ", (sw.peek().msecs/1000), "[sec]");

}

It has both serial and parallel versions. Just comment/uncomment 
as per comments.
Mar 01 2013
parent reply FG <home fgda.pl> writes:
I suppose this:

immutable long DIM = 1024L*1024L *128L;
immutable(double)[] signal = new double[DIM+1];
static this() {
     for (long i=0L; i< DIM+1; i++) {
         signal[i] = (i+DIM)%7 + (i+DIM+1)%5;
     }
}
void main()
{ ... }
Mar 01 2013
parent reply "Sparsh Mittal" <sparsh0mittal gmail.com> writes:
On Friday, 1 March 2013 at 20:28:19 UTC, FG wrote:
 I suppose this:

 immutable long DIM = 1024L*1024L *128L;
 immutable(double)[] signal = new double[DIM+1];
 static this() {
     for (long i=0L; i< DIM+1; i++) {
         signal[i] = (i+DIM)%7 + (i+DIM+1)%5;
     }
 }
 void main()
 { ... }
Thanks. This gives an error, which I don't know how to resolve: Error: cannot evaluate new double[](134217729LU) at compile time Can you please tell.
Mar 01 2013
parent FG <home fgda.pl> writes:
On 2013-03-01 22:05, Sparsh Mittal wrote:
 On Friday, 1 March 2013 at 20:28:19 UTC, FG wrote:
 I suppose this:

 immutable long DIM = 1024L*1024L *128L;
 immutable(double)[] signal = new double[DIM+1];
 static this() {
     for (long i=0L; i< DIM+1; i++) {
         signal[i] = (i+DIM)%7 + (i+DIM+1)%5;
     }
 }
 void main()
 { ... }
Thanks. This gives an error, which I don't know how to resolve: Error: cannot evaluate new double[](134217729LU) at compile time Can you please tell.
Oh, sorry. Was typing without thinking. :) Here's a working sample (with long changed to uint): import std.stdio, std.datetime, std.parallelism, std.range; double my_abs(double n) { return n > 0 ? n : -n; } immutable uint DIM = 1024 * 1024 * 128; immutable(double)[] signal; static this() { auto temp = new double[DIM+1]; for (uint i = 0; i < DIM + 1; i++) temp[i] = (i + DIM) % 7 + (i + DIM + 1) % 5; signal = cast(immutable)temp; } void main() { double temp; double sample[2] = [4.1,7.2]; StopWatch sw; sw.start(); for (uint i = 0; i < DIM; i++) { temp = my_abs(sample[0]-signal[i]) + my_abs(sample[1]-signal[i+1]); } sw.stop(); writeln(" Total time: ", (sw.peek().msecs/1000), "[sec]"); }
Mar 01 2013
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Sparsh Mittal:

 So, is there a way, an array can be made immutable and still 
 initialized? Thanks a lot for your time.
There are various ways to do it. One of the safest way to do it is to create a mutable array inside a strongly pure function, and then when you return it assign it to immutable: import std.stdio, std.datetime, std.range; double myAbs(in double n) pure nothrow { return n > 0 ? n : -n; } enum long DIM = 1024L * 1024L * 128L; double[] genSignal() pure nothrow { auto signal = new double[DIM + 1]; foreach (immutable i; 0 .. DIM + 1) { signal[i] = (i + DIM) % 7 + (i + DIM + 1) % 5; } return signal; } void main() { immutable signal = genSignal(); double sample[2] = [4.1, 7.2]; StopWatch sw; sw.start; foreach (immutable i; 0 .. DIM) { double temp = myAbs(sample[0] - signal[i]) + myAbs(sample[1] - signal[i + 1]); } sw.stop; writeln(" Total time: ", sw.peek.msecs / 1000, "[sec]"); } A less safe way to do it is to use assumeUnique from Phobos. Bye, bearophile
Mar 01 2013
parent reply "Sparsh Mittal" <sparsh0mittal gmail.com> writes:
     foreach (immutable i; 0 .. DIM + 1) {
Thanks. However, rdmd gives error on this line: temp1.d(12): Error: no identifier for declarator immutable(i)
Mar 01 2013
next sibling parent reply "Sparsh Mittal" <sparsh0mittal gmail.com> writes:
Removing immutable word solves the problem. Thanks.
Mar 01 2013
parent "Sparsh Mittal" <sparsh0mittal gmail.com> writes:
I realized that  access to "temp" causes bottleneck. On defining 
it inside for loop, it become local and then there is speedup. 
Defining it outside makes it shared, which slows the program.
Mar 01 2013
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Sparsh Mittal:

 Thanks. However, rdmd gives error on this line:

 temp1.d(12): Error: no identifier for declarator immutable(i)
Probably v.2.062 of the D compiler is enough to not see that error. Bye, bearophile
Mar 01 2013