小编atl*_*ste的帖子

最快的log2(int)和log2(float)实现

问题是

是否还有其他(和/或更快)的基本2log实现?

应用

log2(int)和log2(float)操作在许多不同的上下文中非常有用.仅举几例:压缩算法,3d引擎和机器学习.在几乎所有这些上下文中,它们都被用在被称为数十亿次的低级代码中......尤其是log2(int)操作非常有用.

因为我发现自己一直在使用log2,所以我不想给出我正在处理的特定应用程序.同样的事实是,这是一个真正的性能排水器(如各种应用程序的性能测试所示).对我来说,尽可能快地获得这个是关键.

底部添加了测试所有实现的完整源代码,因此您可以自己查看.

当然......至少运行3次测试并确保计数器大到足以达到几秒钟.我也做'添加'操作,以确保整个循环不被JIT'ter神奇地删除.让我们开始真正的工作吧.

琐碎的实施

C#中2log的简单实现是:

(int)(Math.Log(x) / Math.Log(2))
Run Code Online (Sandbox Code Playgroud)

这个实现很简单,但也很慢.它需要2个Log操作,这本身就很慢.当然,我们可以通过设定1.0/Math.Log(2)常数来优化它.

请注意,我们需要稍微修改此常量以获得正确的结果(作为浮点错误的结果)或添加一个小数字以获得正确的结果.我选择了后者,但这并不重要 - 最终结果在所有情况下都很慢.

表查找

更快的解决方案是使用查找表.虽然您可以使用任何2的幂的查找表,但我通常使用256或64K条目的表大小.

首先我们创建查找表:

lookup = new int[256];
for (int i = 1; i < 256; ++i)
{
    lookup[i] = (int)(Math.Log(i) / Math.Log(2));
}
Run Code Online (Sandbox Code Playgroud)

接下来,我们实现2log如下:

private static int LogLookup(int i)
{
    if (i >= 0x1000000) { return lookup[i >> 24] + 24; }
    else if (i >= 0x10000) { return lookup[i >> 16] + 16; }
    else if (i >= 0x100) { return …
Run Code Online (Sandbox Code Playgroud)

.net c# math performance

22
推荐指数
2
解决办法
9129
查看次数

为什么C#中的空结构消耗内存

我总是理解结构(值类型)包含结构字段中定义的字节数...但是,我做了一些测试,并且空结构似乎有一个例外:

public class EmptyStructTest
{
    static void Main(string[] args)
    {
        FindMemoryLoad<FooStruct>((id) => new FooStruct());
        FindMemoryLoad<Bar<FooStruct>>((id) => new Bar<FooStruct>(id));
        FindMemoryLoad<Bar<int>>((id) => new Bar<int>(id));
        FindMemoryLoad<int>((id) => id);
        Console.ReadLine();
    }

    private static void FindMemoryLoad<T>(Func<int, T> creator) where T : new()
    {
        GC.Collect(GC.MaxGeneration);
        GC.WaitForFullGCComplete();
        Thread.MemoryBarrier();
        long start = GC.GetTotalMemory(true);

        T[] ids = new T[10000];
        for (int i = 0; i < ids.Length; ++i)
        {
            ids[i] = creator(i);
        }

        long end = GC.GetTotalMemory(true);
        GC.Collect(GC.MaxGeneration);
        GC.WaitForFullGCComplete();
        Thread.MemoryBarrier();

        Console.WriteLine("{0} {1}", ((double)end-start) / 10000.0, ids.Length);
    }

    public struct …
Run Code Online (Sandbox Code Playgroud)

.net c# generics memory-management value-type

14
推荐指数
2
解决办法
3841
查看次数

分配引用类型时,c#中的奇怪stackoverflow

在做一些奇特的代码生成时,我遇到了一个我不理解的堆栈溢出.

我的代码基本上是这样的:

static Tuple<string, int>[] DoWork() 
{
    // [ call some methods ]
    Tuple<string, int>[] tmp = new Tuple<string, int>[100];
    tmp[0] = new Tuple<string, int>("blah 1", 0);
    tmp[1] = new Tuple<string, int>("blah 2", 1);
    tmp[2] = new Tuple<string, int>("blah 3", 2);
    // ...
    tmp[99] = new Tuple<string, int>("blah 99", 99);
    return tmp;
}
Run Code Online (Sandbox Code Playgroud)

如果你使用这里的小数字(100)一切正常.如果数字很大,就会发生奇怪的事情.在我的情况下,我尝试发出大约10K行代码,这会触发堆栈溢出异常.

那么......为什么我认为这很奇怪:

  • tmp是引用类型的本地,因此我希望只在堆上分配指针.
  • 元组是引用类型并在堆上分配.
  • 没有递归或其他怪异; afaik应该限制堆上的存储要求.

再现陌生感......

我无法在最小的测试用例中重现stackoverflow,但我确实注意到它似乎是在64位.NET 4.5上触发的.我能给出的是一些证明正在发生的事情的证据.

另请注意,真正的代码使用Reflection.Emit代码生成此代码...它不像代码本身具有所有这些代码行...发出的IL代码是正确的BTW.

在Visual Studio中 - 在最后一行放置一个断点.注意在反汇编中使用堆栈指针(ASM,而不是IL).

现在在代码中添加一个新行 - 例如tmp[100] = // the usuals.在这里放一个断点,注意使用的堆栈空间增长.

至于尝试使用最小的测试用例来重现Reflection.Emit …

.net c# stack-overflow

13
推荐指数
1
解决办法
531
查看次数

向IntelliSense提供不应修改部分类的提示

最近我使用了相当多的代码生成,通常与部分类相结合.基本上设置如下:

  • 包含生成代码的部分类.其中一些代码将调用部分方法.代码重新生成了很多时间.代码生成器在某些情况下是自定义工具.
  • 部分方法在单独的文件中手动实现.

问题是当我使用像"生成方法"这样的Intellisense功能时,它们由于某种原因在包含生成代码的文件中生成.显然我不希望这样.

我的问题是:是否有可能生成一些提示告诉Intellisense它不应该触摸某些'cs'文件(而是其他部分类)?


更新

回想起来,我应该注意到我正在使用自定义工具来生成代码.它不是EF或简单的转换; 代码生成中涉及到相当多的逻辑.此外,它还使用部分类生成完整的命名空间和类结构.通过从csproj文件中提取"root命名空间" 然后使用文件夹结构来确定绝对命名空间(它与Linq2sql的工作方式类似).

xanatos(谢谢!)建议的答案有效:intellisense对名称进行操作排序,然后按字母顺序对名称进行排序,然后选择列表中的第一项.这意味着您可以生成一个zzzz.foo.cs(虽然有点难看)将正常工作.我刚刚进行了一些实验,发现该功能find all references返回了VS似乎使用的顺序.事实证明,它的工作原理如下:

假设您有一个自定义工具,可以处理文件名foo.bar并将其转换为foo.cs.自定义工具将生成内容作为字符串并将其传递回Visual studio(这就是自定义工具的工作方式......).结果将在一个名为的文件中foo.cs.

现在,我很惊讶地发现Intellisense不会将其排序为foo.cs而是将其排序为foo.bar\foo.cs.换句话说:无论你如何命名您的自定义工具"CS"的输出,你必须到基本文件重命名foo.bar为类似zoo.bar.

虽然这可能是一种解决方法,但我很愿意接受它作为答案,因为我必须给我的项目中的文件奇怪的名字(名字有意义......).此外,我的一些自定义工具依赖于他们的文件名,因此也会被破坏...

因此,我仍然愿意就如何正确解决这个问题提出建议.

c# intellisense code-generation

12
推荐指数
1
解决办法
178
查看次数

是否收集了MakeGenericType /泛型类型的垃圾?

在.NET中众所周知,类型不是垃圾收集,这意味着如果你正在玩f.ex. Reflection.Emit,你必须要小心卸载AppDomains等等......至少我是如何理解事情是如何运作的.

这让我想知道泛型类型是否是垃圾收集的,更准确一点:用MakeGenericType例如基于用户输入创建的泛型.:-)

所以我构建了以下测试用例:

public interface IRecursiveClass
{
    int Calculate();
}

public class RecursiveClass1<T> : IRecursiveClass 
                                  where T : IRecursiveClass,new()
{
    public int Calculate()
    {
        return new T().Calculate() + 1;
    }
}
public class RecursiveClass2<T> : IRecursiveClass
                                  where T : IRecursiveClass,new()
{
    public int Calculate()
    {
        return new T().Calculate() + 2;
    }
}

public class TailClass : IRecursiveClass
{
    public int Calculate()
    {
        return 0;
    }
}

class RecursiveGenericsTest
{
    public static int CalculateFromUserInput(string str)
    { …
Run Code Online (Sandbox Code Playgroud)

.net c# generics garbage-collection types

11
推荐指数
1
解决办法
2352
查看次数

Func <T>的性能和继承

Func<...>在使用继承和泛型时,我一直无法理解在整个代码中使用的性能特征- 这是我发现自己一直使用的组合.

让我从一个最小的测试用例开始,这样我们都知道我们在谈论什么,然后我会发布结果,然后我将解释我期望的内容以及为什么......

最小的测试用例

public class GenericsTest2 : GenericsTest<int> 
{
    static void Main(string[] args)
    {
        GenericsTest2 at = new GenericsTest2();

        at.test(at.func);
        at.test(at.Check);
        at.test(at.func2);
        at.test(at.Check2);
        at.test((a) => a.Equals(default(int)));
        Console.ReadLine();
    }

    public GenericsTest2()
    {
        func = func2 = (a) => Check(a);
    }

    protected Func<int, bool> func2;

    public bool Check2(int value)
    {
        return value.Equals(default(int));
    }

    public void test(Func<int, bool> func)
    {
        using (Stopwatch sw = new Stopwatch((ts) => { Console.WriteLine("Took {0:0.00}s", ts.TotalSeconds); }))
        {
            for (int i = 0; i < 100000000; …
Run Code Online (Sandbox Code Playgroud)

.net c# generics performance inheritance

10
推荐指数
1
解决办法
3444
查看次数

从LLVM调用Win32/64函数的正确方法是什么?

我正在尝试将LLVM IR中的方法调用回C++代码.我正在使用64位Visual C++,或者正如LLVM所描述的那样:

Machine CPU:      skylake
Machine info:     x86_64-pc-windows-msvc
Run Code Online (Sandbox Code Playgroud)

对于整数类型和指针类型,我的代码工作正常.但是,浮点数似乎有点奇怪.

基本上这个电话看起来像这样:

struct SomeStruct 
{
    static void Breakpoint( return; } // used to set a breakpoint
    static void Set(uint8_t* ptr, double foo) { return foo * 2; }
};
Run Code Online (Sandbox Code Playgroud)

和LLVM IR看起来像这样:

define i32 @main(i32, i8**) {
varinit:
  // omitted here: initialize %ptr from i8**. 
  %5 = load i8*, i8** %instance0

  // call to some method. This works - I use it to set a breakpoint
  call void @"Helper::Breakpoint"(i8* %5)

  // this …
Run Code Online (Sandbox Code Playgroud)

llvm calling-convention c++11 llvm-ir

10
推荐指数
1
解决办法
497
查看次数

为什么我的设计器属性不是在ASPX中序列化的

为了创建应该在ASP.NET中使用的自定义数据源,我创建了一个自定义数据源类,一个自定义编辑器和一个自定义可序列化类.

我无法理解的是为什么它不起作用......即使我可能有更多的属性而不是必需的(我一直在浏览和尝试几个小时),从我的理解PersistenceMode(PersistenceMode.InnerProperty)应该做的诀窍......此外,在我看来,我的代码类似于为什么我不能在WebForm中声明UserControl的子元素(属性)?.

代码的工作原理如下:

[ParseChildren(true)]
[PersistChildren(true)]
public class MyDataSource : DataSourceControl
{
    // [much more irrelevant code...]

    [Browsable(true)]
    [EditorBrowsable(EditorBrowsableState.Always)]
    [PersistenceMode(PersistenceMode.InnerProperty)]
    [MergableProperty(false)]
    [TypeConverter(typeof(ExpandableObjectConverter))]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [Editor(typeof(Editors.ResultRequestEditor), typeof(System.Drawing.Design.UITypeEditor))]
    public ResultRequest Request { get; set; }
}

[Serializable]
[PersistChildren(true)]
[TypeConverter(typeof(ExpandableObjectConverter))]
[ParseChildren(true)]    
public class ResultRequest
{
    [Browsable(true)]
    [EditorBrowsable(EditorBrowsableState.Always)]
    public string ColumnName { get; set; }

    [Browsable(true)]
    [EditorBrowsable(EditorBrowsableState.Always)]
    public Type ColumnType { get; set; }

    [Browsable(false)]
    [EditorBrowsable(EditorBrowsableState.Always)]
    public object[] ResultTypeParameters { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

自定义编辑器似乎工作:使用它后,VS中的属性正确更新.

但是,在更新某些内容后,信息不会保留在ASPX文件中:

<cc1:MyDataSource ID="SearchDataSource1" runat="server" ProviderID="MyProvider1" />
Run Code Online (Sandbox Code Playgroud)

我期望的是数据源中的一些序列化,例如: …

c# asp.net controls datasource editor

9
推荐指数
1
解决办法
269
查看次数

.NET运行时如何移动内存?

众所周知,.NET垃圾收集器不只是"删除"堆上的对象,而且还使用内存压缩来对抗内存碎片.根据我的理解,基本上将内存复制到一个新的地方,旧的地方在某些时候被删除.

我的问题是:这是如何工作的?

我最感兴趣的是GC在一个单独的线程中运行,这意味着我们正在处理的对象可以在我们执行代码时由GC移动.

问题的技术细节

为了说明,让我更详细地解释一下我的问题:

class Program
{
    private int foo;
    public static void Main(string[] args)
    {
        var tmp = new Program(); // make an object
        if (args.Length == 2)    // depend the outcome on a runtime check
        {
            tmp.foo = 12;        // set value ***
        }
        Console.WriteLine(tmp.foo);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这个小例子中,我们创建一个对象并在对象上设置一个简单变量.点'***'对问题来说很重要:如果'tmp'的地址移动,'foo'会引用不正确的东西,一切都会破坏.

垃圾收集器在单独的线程中运行.所以据我所知,'tmp'可以在这个指令中移动,'foo'最终会得到不正确的值.但不知何故,魔法发生了,但事实并非如此.

至于反汇编程序,我注意到编译后的程序确实采用了'foo'的地址并移动了值'12:

000000ae 48 8B 85 10 01 00 00 mov         rax,qword ptr [rbp+00000110h] 
000000b5 C7 40 08 0C 00 00 00 mov         dword ptr [rax+8],0Ch 
Run Code Online (Sandbox Code Playgroud)

我或多或少期望在这里看到一个间接指针,可以更新 …

.net c# garbage-collection runtime

9
推荐指数
1
解决办法
944
查看次数

LLVM MCJIT/SEH异常处理

最近,我一直试图让SEH异常处理与MCJIT一起在LLVM(3.8.1)中工作.到目前为止没有运气.

根据我从网站(http://llvm.org/docs/ExceptionHandling.html)的理解,这几乎是如何实现的.使用clang编译一小段代码可以得到几乎相同的LLVM IR代码.然而,当我尝试它时,程序崩溃了一个令人讨厌的Stack cookie instrumentation code detected a stack-based buffer overrun..

为了说明我一直在尝试做的事情,我创建了一个最小的测试用例(我为代码量道歉...):

#include <string>
#include <iostream>
#include <exception>

#pragma warning(push)
#pragma warning(disable: 4267)
#pragma warning(disable: 4244)
#pragma warning(disable: 4800)
#pragma warning(disable: 4996)
#pragma warning(disable: 4141)
#pragma warning(disable: 4146)
#pragma warning(disable: 4624)
#pragma warning(disable: 4291)

#define DONT_GET_PLUGIN_LOADER_OPTION

#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Triple.h"
#include "llvm/PassRegistry.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Type.h" …
Run Code Online (Sandbox Code Playgroud)

exception-handling seh llvm llvm-ir

7
推荐指数
1
解决办法
639
查看次数