Notifications
Clear all

[Closed] Maxscript challenge ideas

That’s the algorithm I’ve tried to use

Anyway, just tried swapping the values using XOR swapping but it’s slower that maxscript swap, anyway, here’s the code:

(
	print "V9"
	gc()
	mem = heapfree
	start = timestamp()
	seed(timestamp())
	
	asize = 1000000

	results = for i = 1 to asize collect i
	for i = 1 to asize do 
	(
		idx = random i asize
		v1 = results[i]
		v2 = results[idx]
		v1 = bit.xor v1 v2
		v2 = bit.xor v1 v2
		v1 = bit.xor v1 v2
		
		results[i] = v1
		results[idx] = v2
	)
	
	end = timestamp()
	format "processing: % seconds heap: %
" ((end - start) / 1000.0) (mem-heapfree)
	format "Num unique elem %
" (results as bitarray).numberset
)

Results:

"V9"
processing: 3.651 seconds heap: 416065400L
Num unique elem 1000000
OK

for your knowledge…
all bit structure operations called directly from the structure causes big memory leaking.
put the function to a variable and call from there, and you will see the difference:


 (
 	gc()
 	m1 = heapfree
 	for k=1 to 100000 do bit.xor 1 2
 	format "memory:%
" (m1 - heapfree)
 )
 (	 
 	gc()
 	m1 = heapfree
 	xor = bit.xor
 	for k=1 to 100000 do xor 1 2
 	format "memory:%
" (m1 - heapfree)
 )
  

it works for any structure and any function from the structure.

Gotcha, thanks Denis. BTW any ideia why this is way slower than the max swap function ?

I checked the values for a 1000 element array and the shuffling seemed pretty good. Here is the code:

public class RandomNumberGenerator
{
	public static int [ ] CreateRandomInts ( int count )
	{
		//Stopwatch sw = new Stopwatch ( );
		//sw.Start ( );

		int [ ] arr = new int [ count ];
		for ( int i = 0; i < count; ++i )
			arr [ i ] = i;

		var arr2 = Shuffle ( arr );

		//sw.Stop ( );

		//Console.WriteLine ( sw.ElapsedMilliseconds / 1000.0 );
		return arr2;
	}

	public static T [ ] Shuffle<T> ( T [ ] array )
	{
		Random rnd = new Random ( );

		T [ ] newArray = new T [ array.Length ];
		array.CopyTo ( newArray, 0 );
		for ( int i = 0; i < array.Length; ++i )
		{
			int index = rnd.Next ( i, array.Length );
			if ( index != i )
			{
				T temp = newArray [ i ];
				newArray [ i ] = newArray [ index ];
				newArray [ index ] = temp;
			}
		}

		return newArray;
	}
}

Light

Mine’s just your code tweaked to use the algorithm I’d posted in mxs.

I didn’t spend any time optimizing the C#, I just wanted to compare apples to apples and see how fast a compiled version ran.

fn myCreateArrAssembly =
(
	source = ""
	source += "using System;
"
	source += "using System.Collections;
"
	source += "namespace MathOps
"
	source += "{
"
	source += "    public class myArrayClass
"
	source += "    {
"
	source += "        private Int32[] RandomizeIndexes(int count, Random list)
"
	source += "        {
"
	source += "	         Int32 j;"
	source += "            Int32[] randoms = new Int32[count];
"
	source += "	         randoms[0] = 1;"
	source += "            for (int i = 1; i < count; i++)
"
	source += "            {
"
	source += "               j = list.Next(0,i+1);"
	source += "               randoms[i] = randoms[j];
"
	source += "                randoms[j] = i+1;
"
	source += "            }
"
	source += "           return randoms;
"
	source += "        }
"
	source += "        public Int32[] RandomIndexes(int count)
"
	source += "        {
"
	source += "            Random list = new Random();
"
	source += "            return RandomizeIndexes(count, list);
"
	source += "        }
"
	source += "        public Int32[] RandomIndexes(int count, int seed)
"
	source += "        {
"
	source += "            Random list = new Random(seed);
"
	source += "            return RandomizeIndexes(count, list);
"
	source += "        }
"
	source += "    }
"
	source += "}
"

	csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
	compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"

	compilerParams.ReferencedAssemblies.AddRange #("System.dll")

	compilerParams.GenerateInMemory = on
	compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
	
			if (compilerResults.Errors.Count > 0 ) then
			(
				errs = stringstream ""
				for i = 0 to (compilerResults.Errors.Count-1) do
				(
					err = compilerResults.Errors.Item[i]
					format "Error:% Line:% Column:% %
" err.ErrorNumber err.Line \                                              
														 err.Column err.ErrorText to:errs 
				)
				MessageBox (errs as string) title: "Errors encountered while compiling C# code"
				format "%
" errs
				return undefined
			)
	
	assembly = compilerResults.CompiledAssembly
	assembly.CreateInstance "MathOps.myArrayClass"
)

global myArrayClass = myCreateArrAssembly()
fn myrandomIndexes count seedvalue: asdotnetobject:off = 
(
	if not iskindof seedvalue Integer 
		then myArrayClass.RandomIndexes count asdotnetobject:asdotnetobject
		else myArrayClass.RandomIndexes count seedvalue:seedvalue asdotnetobject:asdotnetobject
)



3 Replies
(@light)
Joined: 10 months ago

Posts: 0

Is this way of compiling be faster in performance than using DotNet.LoadAssembly? It would be cool if it was (:

Cheers,
Light

(@denist)
Joined: 10 months ago

Posts: 0

it’s not faster probably. usually for small assemblies i use on-fly compiling method, for bigger but easy for debugging i use dynamic dll loading. for dlls that really need debugging i use loadassembly with complete restating of max.
on-fly compiling just allows me rebuild the assembly every time when i need it for any purpose.

(@light)
Joined: 10 months ago

Posts: 0

Yes I tried it, it’s about 15-20ms slower.

The conversion from .NET to Mxs takes a lot of time like biddle said. If I use specify the asDotNetObject parameter as true, mine drops to 0.022s. Significant saving for sure.

Light

The vast majority of the time is spent converting the million element .NET array to MXS array:


(
	gc()
	local limit = 1000000
	
	local startM = heapfree
	local startT = timestamp()

	local a = myrandomIndexes  limit asdotnetobject:off
	format "

Return an mxs array:
Time: %s, Mem: %Kb
" ((timestamp()-startT)/1000.0) (((startM-heapfree) as integer)/1024)
	format "Num unique elem %
" (a as bitarray).numberset
)

(
	gc()
	local limit = 1000000
	
	local startM = heapfree
	local startT = timestamp()

	local a = myrandomIndexes  limit asdotnetobject:on
	format "

Return a .NET array :
Time: %s, Mem: %Kb
" ((timestamp()-startT)/1000.0) (((startM-heapfree) as integer)/1024)
	--format "Num unique elem %
" (a as bitarray).numberset
)

Return an mxs array:
Time: 1.417s, Mem: 27395Kb
Num unique elem 1000000
OK

Return a .NET array :
Time: 0.048s, Mem: 0Kb
OK

1 Reply
(@denist)
Joined: 10 months ago

Posts: 0

sure… that was a point for me to do c# assembly.

so we have a Winner!
biddle and his little friend – wikipedia


  fn CreateArrAssembly =
  (
  
  source = ""
  source += "using System;
"
  source += "using System.Collections;
"
  source += "namespace MathOps
"
  source += "{
"
  source += "	public class ArrayClass
"
  source += "	{
"
  source += "		public int[] RandomIndexes(int count)
"
  source += "		{
"
  source += "			Random list = new Random();
"
  source += "			int[] numbers = new int[count];
"
  source += "			int[] randoms = new int[count];
"
  source += "			for (int i = 0; i < count; i++)
"
  source += "			{
"
  source += "				randoms[i] = list.Next();
"
  source += "				numbers[i] = i + 1;
"
  source += "			}
"
  source += "			Array.Sort(randoms, numbers);
"
  source += "			return numbers;
"
  source += "		}
"
  
  source += "		public int[] RandomSwapIndexes(int count)
"
  source += "		{
"
  source += "			Random list = new Random();
"
  source += "			int j;
"
  source += "			int[] randoms = new int[count];
"
  source += "			randoms[0] = 1;
"
  source += "			for (int i = 1; i < count; i++)
"
  source += "			{
"
  source += "			   j = list.Next(0, i + 1);
"
  source += "			   randoms[i] = randoms[j];
"
  source += "			   randoms[j] = i + 1;
"
  source += "			}
"
  source += "			return randoms;
"
  source += "		}
"
  
  --------------------------- seed support ------------------------------
  
  source += "		public int[] RandomIndexes(int count, int seed)
"
  source += "		{
"
  source += "			Random list = new Random(seed);
"
  source += "			int[] numbers = new int[count];
"
  source += "			int[] randoms = new int[count];
"
  source += "			for (int i = 0; i < count; i++)
"
  source += "			{
"
  source += "				randoms[i] = list.Next();
"
  source += "				numbers[i] = i + 1;
"
  source += "			}
"
  source += "			Array.Sort(randoms, numbers);
"
  source += "			return numbers;
"
  source += "		}
"
  
  source += "		public int[] RandomSwapIndexes(int count, int seed)
"
  source += "		{
"
  source += "			Random list = new Random(seed);
"
  source += "			int j;
"
  source += "			int[] randoms = new int[count];
"
  source += "			randoms[0] = 1;
"
  source += "			for (int i = 1; i < count; i++)
"
  source += "			{
"
  source += "			   j = list.Next(0, i + 1);
"
  source += "			   randoms[i] = randoms[j];
"
  source += "			   randoms[j] = i + 1;
"
  source += "			}
"
  source += "			return randoms;
"
  source += "		}
"
  
  source += "	}
"
  source += "}
"
  
  		csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
  		compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
  
  		compilerParams.ReferencedAssemblies.AddRange #("System.dll")
  
  		compilerParams.GenerateInMemory = on
  		compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
  		assembly = compilerResults.CompiledAssembly
  		assembly.CreateInstance "MathOps.ArrayClass"
  )
  
  global ArrayClass = CreateArrAssembly()
  
  
  maxlimit = 1000000
  fn indexDensity list parts:5 =
  (
  	sums = 0
  	for k=0 to parts-1 do
  	(
  		sum = 0
  		for i=0 to list.count/parts-1 do
  		(
  			sum += list[k*parts + i + 1]
  		)
  		format "	%: % ? %
" k sum ((maxlimit+1)*(maxlimit/2)/parts)
  		sums += sum
  	)
  	format "	=: % % % = %
" sums "%" ((maxlimit+1)*(maxlimit/2)) (sums*1.0/((maxlimit+1)*(maxlimit/2)))
  )
  
  
  (
  	gc()
  	limit = maxlimit
  	
  	startM = heapfree
  	startT = timestamp()
  
  	a = ArrayClass.RandomSwapIndexes limit 1 asdotnetobject:on
  	format "

Biddle algorithm (thank you wikipedia):
Time: %s, Mem: %Kb
" ((timestamp()-startT)/1000.0) (((startM-heapfree) as integer)/1024)
  --	format "Num unique elem %
" (a as bitarray).numberset
  --	indexDensity a
  )
  (
  	gc()
  	limit = maxlimit
  	
  	startM = heapfree
  	startT = timestamp()
  
  	a = ArrayClass.RandomIndexes limit 1 asdotnetobject:on
  	format "

denisT code:
Time: %s, Mem: %Kb
" ((timestamp()-startT)/1000.0) (((startM-heapfree) as integer)/1024)
  --	format "Num unique elem %
" (a as bitarray).numberset
  --	indexDensity a
  )
  

it’s a template for anyone who to play with

the interesting story behind… my first algorithm was very similar to biddle’s. but i refused it for some reason. i didn’t like the distribution. now i can’t see anything wrong with it.

i can’t compile Light’s code in max. is there something .net 3.5 specific? i don’t see anything.

1 Reply
(@light)
Joined: 10 months ago

Posts: 0

Remove “using System.Linq;”, then it should work.

Light

Mine is the ‘inside out’ variant of Fisher-Yates shuffle

1 Reply
(@denist)
Joined: 10 months ago

Posts: 0

same as Light said…
but Light and me in my research initialize an array and fill it up with sequence. Here we are loosing time and memory.

 lo1

there’s var but that should be in 3.0

Page 9 / 12