|
Does anyone know if LINQ to SQL lets you map interface types to tables? I want to dynamically generate my classes at runtime, and the mapping scheme only seems to work with a statically-compiled class heirarchy. Has anyone had any luck with this?
|
|
|
|
|
Hello,
Yes, you may generate your classes at runtime and thereafter map the objects to the interface. Instead of using a designer tool like “Linq to SQL Class”, you need to provide the mapping objects on your own.
Here is a link for 10 videos being posted by Mike Taulty which might interest you.
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2007/04/26/9254.aspx
Best Regards,
Sam Xavier
www.componentone.com
|
|
|
|
|
I am trying to make a method that computes the floor of the base 2 integer log for another integer. My current code is as follows...
public static byte Log2(int val) {
if (val <= 0)
return byte.MaxValue;
byte rval = 0;
while ((val >> rval) > 1)
++rval;
return rval;
}
Is there a better way to do this, like perhaps a binary search algorithm?
Jeff
|
|
|
|
|
Skippums wrote: like perhaps a binary search algorithm?
what? you show a single integer as input, what are you going to search? Who are you?
|
|
|
|
|
For example, the following code, which takes the middle bit of a bound (0 to 32), and attempts to perform the right shift. If the result is 0, I shifted the number too far, so I make my new range 0 to 16, take the new average (8), and try again. If the number is greater than 1 at that point, you modify the lower bound, so now I am shifting 12 bits (average of 8 and 16). Continue this cycle until you find the magic number that makes the resulting shift equal to 1. This is O(log(n)) time, vs. my initial algorithm of O(n). I did some testing of the two, and the second is far faster for randomly generated numbers, but only because most randomly generated are large. When I set the upper bound to 0x1000 (4096) on the random number size, the two algorithms broke even, taking about .95 s to do 0x1000000 (16,777,216) log base 2 method calls. The code is below...
private byte Log2_2(uint val) {
if (val < 1)
return byte.MaxValue;
byte high = sizeof(uint) << 3;
byte low = 0, med = (byte)(high >> 1);
uint tmp = val >> med;
while (tmp != 1) {
if (tmp == 0)
high = med;
else
low = med;
med = (byte)(low + high >> 1);
tmp = val >> med;
}
return med;
}
Jeff
|
|
|
|
|
Hi Jeff,
I currently have a test fixture for your Log2_2 and some of mine;
for the same number of tests they all yield around one second.
First impression is most of the time is spent in the test fixture, not in the log2 method.
May I suggest you measure again with an empty Log2_2 to check by how much the elapsed
time does (not) drop?
Here is one of my tries:
int LP_log2_3(uint val) {
if(val==0) return -1;
int res=0;
if(val>0x0000FFFF) {res+=16;val>>=16;}
if(val>0x000000FF) {res+=8;val>>=8;}
if(val>0x0000000F) {res+=4;val>>=4;}
if(val>0x00000003) {res+=2;val>>=2;}
if(val>1) res++;
return res;
}
I feel another article coming up, comparing C#, C and asm.
Luc Pattyn [Forum Guidelines] [My Articles]
this months tips:
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use PRE tags to preserve formatting when showing multi-line code snippets
|
|
|
|
|
Yep, that's what I was looking for. The results of 16,777,216 (0x1000000) calls for randomly generated integers:
Gross Net
1. Linear search: 1542 ms 1091 ms
2. Binary search: 887 ms 436 ms
3. Hardcoded Conditionals: 686 ms 235 ms
4. Control (returns constant): 451 ms 0 ms
That speeds it up by a factor of about 1.85; Thanks!
Jeff
|
|
|
|
|
Are these numbers for debug or release build?
Do you call random generator inside the timed loop or did you store its outcome somehow
beforehand?
Luc Pattyn [Forum Guidelines] [My Articles]
this months tips:
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use PRE tags to preserve formatting when showing multi-line code snippets
|
|
|
|
|
1: Release build.
2: Beforehand
Here is the code...
private Stopwatch sw = new Stopwatch();
private List<uint> m_Nums = new List<uint>(0x1000000);
private List<uint> result1 = new List<uint>(0x1000000);
private List<uint> result2 = new List<uint>(0x1000000);
private List<uint> result3 = new List<uint>(0x1000000);
private List<uint> result4 = new List<uint>(0x1000000);
...
private void button1_Click(object sender, EventArgs e) {
m_Nums.Clear();
result1.Clear();
result2.Clear();
result3.Clear();
result4.Clear();
Random rnd = new Random();
for (int i = 0; i < m_Nums.Capacity; ++i)
m_Nums.Add((uint)rnd.Next());
sw.Start();
foreach (uint num in m_Nums)
result1.Add(Log2_1(num));
sw.Stop();
label1.Text = sw.ElapsedMilliseconds.ToString();
sw.Reset();
}
I even tested it in different orders (ie, calling <3,4,1,2>, etc.), to see if the order those methods were being called effects the time taken by them. They were all reasonably constant regardless of the ordering. Oh yeah, and I attempted to make your Conditional method more extensible in a for loop, but it ended up taking the same time (+-10 ms) as my binary search code. I copied it below...
if (val < 1)
return byte.MaxValue;
int shift = sizeof(uint) << 2;
uint mask = uint.MaxValue >> shift;
int rval = 0;
do {
if (val > mask) {
rval += shift;
val >>= shift;
}
shift >>= 1;
mask >>= shift;
} while (shift > 0);
return (byte)rval;
Jeff
|
|
|
|
|
Thanks for the info.
I guess a big part of the overhead is enumerating the testcases and storing the results
in the List (I did sum+=LP_log2(x); to prevent the optimizer to kick it all)
Luc Pattyn [Forum Guidelines] [My Articles]
this months tips:
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use PRE tags to preserve formatting when showing multi-line code snippets
|
|
|
|
|
I don't know if you care, but the results when operating on 64 bit integers are extremely interesting. All the methods start with a zero check, which I omitted to keep this post minimal, and myType is System.Uint64. Here are the methods and the results using the same number of operations as I did for 32 bit integers (0x1000000 each):
Method1
byte high = sizeof(myType) << 3;
byte med = (byte)(high >> 1);
byte low = 0;
myType tmp = val >> med;
while (tmp != 1) {
if (tmp == 0)
high = med;
else
low = med;
med = (byte)(low + high >> 1);
tmp = val >> med;
}
return med; Method2
byte shift = (byte)(sizeof(myType) << 2);
myType mask = myType.MaxValue >> shift;
byte rval = 0;
do {
if (val > mask) {
rval += shift;
val >>= shift;
}
shift >>= 1;
mask >>= shift;
} while (shift > 0);
return rval; Method3
byte res = 0;
if (val > 0xFFFFFFFF) { res += 32; val >>= 32; }
if (val > 0x0000FFFF) { res += 16; val >>= 16; }
if (val > 0x000000FF) { res += 8; val >>= 8; }
if (val > 0x0000000F) { res += 4; val >>= 4; }
if (val > 0x00000003) { res += 2; val >>= 2; }
if (val > 0x00000001) ++res;
return res; Results
Gross Net
Method 1 1366 ms 892 ms
Method 2 2093 ms 1619 ms
Method 3 949 ms 475 ms
Control 474 ms 0 ms
I guess that being able to exit early (as in method 1) REALLY pays off as opposed to how it is being done in method 2 (which, if you remember, tied within 10 ms for 32 bit integers).
Jeff
|
|
|
|
|
Thanks again.
I never was much in favor of method 2 due to its number of conditional tests (2 per iteration,
one for data, one for looping), and its number of right shifts (3 per iteration).
with 64-bit quantities, I trust the JIT is
- not relying on 64-bit registers (I assume you are targetting all x86 models)
- running out of CPU registers (since needing two 32-bit regs for each variable now)
In method 3 you might try and cast the Int64 to an Int32 variable after the first test,
and use the new variable for the remainder of the method, reducing the number of 64-bit
operations.
Luc Pattyn [Forum Guidelines] [My Articles]
this months tips:
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use PRE tags to preserve formatting when showing multi-line code snippets
|
|
|
|
|
There hasn't been a Friday programming quiz for a while, maybe this could be tomorrow's?
|
|
|
|
|
Well some would have a head start then.
May I suggest a new question: given a uint, find the next power of 2. And make it fast!
Luc Pattyn [Forum Guidelines] [My Articles]
this months tips:
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use PRE tags to preserve formatting when showing multi-line code snippets
|
|
|
|
|
Luc Pattyn wrote: And make it fast!
"Fast" as in "not eating clock cycles"?
|
|
|
|
|
Exactly.
I did not mean urgent, otherwise I would have put that in the subject line
Luc Pattyn [Forum Guidelines] [My Articles]
this months tips:
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use PRE tags to preserve formatting when showing multi-line code snippets
|
|
|
|
|
Don't make me explain the pun.
|
|
|
|
|
I'll try not to confuse cycles and calories.
Luc Pattyn [Forum Guidelines] [My Articles]
this months tips:
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use PRE tags to preserve formatting when showing multi-line code snippets
|
|
|
|
|
I wonder how mine would stack up; could you pass them through your test?
I started with this:
public static int
MSB
(
ulong Subject
)
{
int result = 63 ;
if ( Subject != 0 )
{
ulong runner = 1 ;
runner <<= result ;
while ( ( Subject & runner ) == 0 )
{
result-- ;
runner >>= 1 ;
}
}
else
{
result = -1 ;
}
return ( result ) ;
}
Then, taking your idea for binary search, I did this:
public static int
MSB
(
ulong Subject
)
{
return
(
Subject > uint.MaxValue
?
MSB ( (uint) ( Subject >> 32 ) ) + 32
:
MSB ( (uint) Subject )
) ;
}
public static int
MSB
(
uint Subject
)
{
return
(
Subject > ushort.MaxValue
?
MSB ( (ushort) ( Subject >> 16 ) ) + 16
:
MSB ( (ushort) Subject )
) ;
}
public static int
MSB
(
ushort Subject
)
{
return
(
Subject > byte.MaxValue
?
MSB ( (byte) ( Subject >> 8 ) ) + 8
:
MSB ( (byte) Subject )
) ;
}
public static int
MSB
(
byte Subject
)
{
int result = 7 ;
if ( Subject != 0 )
{
byte runner = 128 ;
while ( ( Subject & runner ) == 0 )
{
result-- ;
runner >>= 1 ;
}
}
else
{
result = -1 ;
}
return ( result ) ;
}
|
|
|
|
|
I'm not going to test your first method, because although it will perform very well on the test data I am giving it (randomly produced ulongs), it is still an O(n) operation, and I know it won't perform as well on my actual data which will mostly be on the order of 2^20. However, I did check your other method, and it was clocked at 1081/623 ms (gross/net). This compared to Luc's direct comparison method at 769/311 ms and my first binary search algorithm at 1360/902 ms.
Jeff
|
|
|
|
|
What about this one for the byte-sized data?
(Notice the name change.)
public static int
HighestBitSet
(
byte Subject
)
{
int result = -1 ;
if ( Subject > 15 )
{
Subject >>= 4 ;
result += 4 ;
}
if ( Subject > 3 )
{
Subject >>= 2 ;
result += 2 ;
}
if ( Subject > 1 )
{
Subject >>= 1 ;
result += 1 ;
}
if ( Subject > 0 )
{
result += 1 ;
}
return ( result ) ;
}
|
|
|
|
|
This won't be faster than what I have already implemented, which is directly related. It is identical in logic to the idea proposed by Luc in a previous post. This is the fastest way to do it in C# without importing external unmanaged code (I am pretty certain), but Luc's way will be slightly faster. This is because this new method will, for most values, perform an additional addition operation. For the only remaining value (0), this method will perform worse by 3 unnecessary test cases and one unnecessary initialization (of the variable result). Therefore, there exists NO condition where this code will take fewer operations than Luc's code, so I don't have to test it. However, it will still be very fast, and would improve your previous algorithm's time to within (I'm guessing) ~80 ms of Luc's. The additional time would be spent on pushing and poping data to the runtime stack in calling the various methods.
Jeff
|
|
|
|
|
How about
private static readonly int[] force = new int[]
{ 0 , 1 , 2 , 2 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 } ;
public static int
HighestBitSet
(
byte Subject
)
{
int result = -1 ;
if ( Subject > 15 )
{
Subject >>= 4 ;
result = 3 ;
}
return ( result + force [ Subject ] ) ;
}
-- modified at 23:36 Thursday 29th November, 2007
Whoops, left out the static , decided to add readonly as well.
-- modified at 9:55 Friday 30th November, 2007
|
|
|
|
|
Nice idea! We have a new winner...
private static readonly byte[] s_Log2Vals = new byte[]
{ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
private byte Log2(ulong val) {
int res = -1;
if (val > 0xFFFFFFFF) { res += 32; val >>= 32; }
uint val2 = (uint)val;
if (val2 > 0x0000FFFF) { res += 16; val2 >>= 16; }
if (val2 > 0x000000FF) { res += 8; val2 >>= 8; }
if (val2 > 0x0000000F) { res += 4; val2 >>= 4; }
return (byte)(res + s_Array[val2]);
} The stats are as follows:
Gross Net
Cascading Types: 1046 ms 591 ms
Hard Coded Conditionals: 760 ms 305 ms
Hard Coded Cond. W/ Array: 593 ms 138 ms
Control: 455 ms 0 ms
As you can see, this method (using your idea), only took ~90ms, which increased throughput by a factor of 2.21! Thanks,
Jeff
|
|
|
|
|
Skippums wrote: using your idea
Well, actually it was Luc's.
|
|
|
|
|