向所有人提出问题C#向导.我有一个方法,称之为myFunc,它需要可变长度/类型参数列表.myFunc本身的参数签名是myFunc(params object[] args),我在列表上使用反射(例如,想想这有点像printf).
我想要myFunc(1, 2, 3)区别对待myFunc(new int[] { 1, 2, 3 }).也就是说,在myFunc的主体内,我想枚举我的参数的类型,并希望最终得到{int,int,int}而不是int [].现在我得到后者:实际上,我无法区分这两种情况,它们都以int []的形式出现.
我希望前者显示为obs [].长度= 3,obs [0] = 1等.
而且我曾预计后者会显示为obs [].长度= 1,其中obs [0] = {int [3]}
这可以做到,还是我问不可能?
我正在开发一个多核,多线程软件库,我想在其中提供可能跨越多个缓存行的更新顺序保留无锁共享内存对象.
具体来说,假设我有一些高速缓存行大小的对象的向量X:X [0],... X [K]每个占用恰好一个高速缓存行.我按索引顺序写入它们:首先是X [0],然后是X [1],等等.如果线程2读取X [K],它还会看到X [0]的状态是"至少是当前的"正如它看到的X [K]?
从同一个线程,显然我会看到尊重更新顺序的内存语义.但是现在如果某个第二个线程读取X [K]则会出现问题:是否会观察到对X [0] ...... X [K-1]的相应更新?
通过锁定,我们可以获得此保证.但是由于memcpy用于将某些东西复制到向量中,我们失去了这个属性:memcpy有一个POSIX语义,它不保证索引顺序更新或内存顺序更新或任何其他排序.您可以确保在memcpy完成后,已执行整个更新.
我的问题:是否已经有一个保持订单的memcpy具有相似的速度但具有所需的保证?如果没有,可以在没有锁定的情况下实现这样的原语吗?
假设我的目标平台是x86和ARM.
(编者注:最初称英特尔,所以OP可能不关心AMD.)
我正在使用mkbundle并尝试创建一个使用Isis2的小程序IdaTester的嵌入式版本.该系统反过来使用Mono中依赖MonoPosixHelper的功能
我的问题是mkbundle无法识别依赖项,我最终得到一个仍然需要动态链接〜/ bin/lib/libMonoPosixHelper.so的可执行文件,当我将此可执行文件移动到我不能运行的系统时会导致问题有Mono安装.实际上,捆绑包缺少应该静态链接的东西之一.
我的可执行文件确实有效,但前提是我确保只在具有"正确位置"动态库的机器上运行它.这违背了嵌入式可执行文件的目的......我希望能够将这个程序作为一种服务器交给他们,他们可以把它放在任何地方并作为二进制文件启动,显然如果他们需要安装库来实现这一点,服务器并不是完全独立的!
我看到如何强制mkbundle包含程序所依赖的任何dll文件,但是MonoPosixHelper不作为dll存在; 这是一个仅限Linux的库,仅作为共享库存在.有没有人知道一种"强制"捆绑静态嵌入它的方法?
如果这有帮助,我的小编译脚本如下:
mcs -debug+ IdaTester.cs Isis.cs -r:System.dll -r:Microsoft.CSharp.dll -r:Mono.Posix.dll
mkbundle --static -o IdaTester IdaTester.exe --deps
Run Code Online (Sandbox Code Playgroud)
然后我运行IdaTester; 这适用于可以找到libMonoPosixHelper库的平台,但是如果在尚未安装libMonoPosixHelper的平台上运行时尝试动态加载该库,则会在运行时失败...
我的小组(一个名为 Isis2 的项目)正在试验 RDMA。我们对缺乏单方面 RDMA 读取的原子性保证的文档感到困惑。在过去的一个半小时里,我一直在寻找有关这方面的任何信息,但无济于事。这包括仔细阅读 rdmamojo.com 上的博客,该博客以回答每个 RDMA 问题而闻名......
在我们关注的情况下,我们希望编写器对始终适合单个缓存行的对象进行原子写入。假设这发生在机器 A 上。然后我们计划在机器 B 上有一个单边原子 RDMA 读取器,它可以从 A 读取大块内存,跨越许多这些对象(但同样,没有对象会被非原子地写入,并且所有内容都将适合某个单个缓存行)。因此 B 读取 X、Y 和 Z,并且这些对象中的每一个都位于 A 上的一个缓存行中,并使用原子写入进行写入。
因此,原子写入将是本地的,但 RDMA 读取将从远程机器到达,并且在没有本地 CPU 参与的情况下完成。
尽管是在远程机器上启动的,我们的单边读取是否与原子本地读取“语义等效”?(我怀疑是这样:否则,单边 RDMA 读取对于曾经修改过的数据将毫无用处......)。“规则”记录在哪里?
当在现代无锁内存上使用单侧 RDMA 时,会出现这样的问题:如果数据对象跨越多个缓存行,远程读取器如何安全地查看其传入数据。
\n在 Derecho 开源多播和复制日志库(位于https://GitHub.com/Derecho-Project上)中,我们有这种模式。写入器 W 被授予写入读取器 R 中的一系列内存的权限。内存已正确固定和映射。现在,假设写入涉及跨越许多缓存行的某种数据向量,这很常见。我们使用一个守卫:一个递增的计数器(也在 RDMA 可访问内存中,但在其他一些缓存行中)。R 旋转,当它看到变化时观察计数器\xe2\x80\xa6,这告诉 R \xe2\x80\x9c 你有一条新消息\xe2\x80\x9d,然后 R 读取向量中的数据。后来我们有第二种模式,R 对 W 说,\xe2\x80\x9c我已经处理完该消息,你可以发送另一条消息。\xe2\x80\x9d
\n我的问题:对于现代内存模型,应该使用哪种 C++ 原子风格来写入向量的内存?这会被称为宽松一致性吗?我希望我的代码能够在 ARM 和 AMD 上运行,而不仅仅是具有强大 TSO 内存模型的英特尔。
\n那么对于我的计数器,当 R 旋转监视计数器更新时,我希望如何声明计数器?是否需要将其声明为获取-释放原子?
\n最后,在 R 观察到计数器已增加之后,就速度或正确性而言,将所有内容声明为宽松的,然后在此处使用内存顺序栅栏是否有任何优点?我的想法是,通过第二种方法,我在所有 RDMA 内存上使用最小一致性模型(并对所有此类内存使用相同的模型),而且我只需要在观察到计数器增加后调用成本更高的内存顺序栅栏。因此,在访问我的向量之前,它只发生一次,而每次我的轮询线程循环时,获取释放原子计数器都会触发内存防护机制。对我来说,这听起来非常昂贵。
\n最后一个想法又引出了一个问题:我是否也必须将此内存声明为易失性,以便 C\xe2\x80\x94 编译器意识到数据可以在其脚下更改,或者编译器本身可以看到数据就足够了std::原子类型声明?在Intel上,对于全店订购,肯定需要TSO加上易失性。
\n[编辑:新信息](我试图在这里吸引一些帮助!)
\n一种选择似乎是将 RDMA 内存区域声明为 std::atomic<relaxed_consistency> 但每次我们的谓词评估线程重新测试防护时都使用锁(在 RDMA 内存中,将使用相同的宽松属性进行声明) )。我们将保留 C++ 易失性注释。
\n原因是,使用具有获取-释放语义的锁,内存一致性硬件将被警告它需要隔离先前的更新。锁本身(互斥体)可以声明为谓词线程本地的,然后将存在于本地 DRAM 中,这是便宜的,并且由于这不是任何东西争用的锁,因此锁定它可能与 test_and_set 一样便宜,并且解锁只是写入 0。如果谓词为 true,我们的触发代码体将在访问锁之后运行(可能是在锁释放之后),因此我们建立所需的顺序以确保硬件将获取受保护的对象使用实际的内存读取。但是,通过谓词测试的每个周期(每次“旋转”),我们最终都会对每个谓词执行锁定获取/释放。所以这会导致一些速度减慢。
\n选项二看似开销较小,也将 RDMA 区域声明为具有宽松一致性的 std::atomic,但省略了锁并像我们现在一样进行测试。然后,当谓词测试为真时,我们将使用语义执行显式内存栅栏(std::memory-order)。我们得到相同的屏障,但仅在谓词评估为 true 时才支付成本,因此开销更少。
\n但现在我们遇到了一个不同类型的问题。Intel 有总存储顺序 TSO,并且由于任何线程都会执行一些先写后读操作,Intel …
只是好奇:当然,我们都知道泛型类型推断的一般情况是不可判定的.所以C#根本不做任何类型的子类型:如果Foo <T>是泛型的,Foo <int>不是Foo <T>的子类型,或Foo <Object>或其他任何你可能的类型做饭.当然,我们都用丑陋的界面或抽象类定义来解决这个问题.
但是......如果你无法解决一般性问题,为什么不将解决方案限制在容易的情况下.例如,在上面的列表中,显然Foo <int>是Foo <T>的子类型,并且检查它是微不足道的.检查Foo <Object>是一样的.
如果他们只是说,那么还有其他一些深深的恐怖会从深渊蔓延出来,我们会尽我们所能吗?或者这只是微软语言人员的某种宗教纯洁?
这是一个非常古老的线程.这些天,C#有var,它解决了我抱怨的一半,然后使用Linq风格的匿名代表,有一个很好的表示法,不需要输入两次相同的东西.因此,我反对的每一个方面都已经通过最近对C#的更改得到了解决(或者我只是花了一些时间来了解我刚发布帖子时刚刚介绍的内容......)我使用这些新内容现在在Isis2系统中可靠的云计算功能(isis2.codeplex.com),我认为该库具有非常干净的外观和感觉.看看它,让我知道你的想法). - Ken Birman(2014年7月)
这是对先前线程的一种后续行为.我正在构建一个小包装器来对我的用户提供的动态类型化方法进行upcalls.该方案运作良好......但仅适用于静态方法.虽然CreateDelegate也适用于实例方法,但是当与那些方法一起使用时,如果方法isStatic标志为false,它会抛出"绑定错误"(实际上,因为我有throw-on-error标志为false,它返回null) .这是一个代码示例,您可以在其中看到这种情况.
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleApplication4
{
delegate void myFoo(int i, string s);
delegate void myNull();
internal class Callable
{
internal int nParams;
internal Type[] ptypes;
internal Delegate cb;
internal static Type[] actions = { typeof(Action), typeof(Action<>), typeof(Action<,>), typeof(Action<,,>), typeof(Action<,,,>), typeof(Action<,,,,>),
typeof(Action<,,,,,>), typeof(Action<,,,,,,>), typeof(Action<,,,,,,,>), typeof(Action<,,,,,,,,>), typeof(Action<,,,,,,,,,>),
typeof(Action<,,,,,,,,,,>), typeof(Action<,,,,,,,,,,,>), typeof(Action<,,,,,,,,,,,,>), typeof(Action<,,,,,,,,,,,,,>), typeof(Action<,,,,,,,,,,,,,,>) };
internal Callable(Delegate hisCb)
{
MethodInfo mi = hisCb.Method;
ParameterInfo[] pi = mi.GetParameters();
ptypes = pi.Select(p => p.ParameterType).ToArray();
nParams = ptypes.Length; …Run Code Online (Sandbox Code Playgroud) 我的用户传给我一些类型的数组,比如int []或string [].我可以通过GetElementType轻松查询元素的类型,我可以通过GetRank,GetLength等查看数组传递给我的时间.
数组在params列表中传递,因此可视化代码如下:
public void Resizer(params object[] objs)
{
foreach (object o in objs)
Array.Resize(ref o, 3);
}
Run Code Online (Sandbox Code Playgroud)
我想要做的是与可用的Get方法相反并且确实有效:我想调整传递给我的数组的大小,将长度设置为其他长度(在这个愚蠢的例子中就像3).
我这样做是因为在我的设置中,数组将包含从一组云计算服务器接收的数据,我们无法知道有多少人会提前响应,因此无法预先分配数组以获得正确的长度.理想情况下,实际上,我的用户传入一个长度为0的数组,然后传回一个长度为n的数组,表示我从查询服务器获得了n个回复.
我无法使用Array.Resize(ref T,int)执行此操作,因为我在编译时不知道T.
有没有办法解决这个问题?
这是我认为昨天解决的一个帖子的后续内容.昨天我在以下情况下遇到了我的代码问题:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
class Bar
{
int v;
public Bar(int v) { this.v = v; }
public override string ToString() { return v.ToString(); }
}
static void Main(string[] args)
{
Foo(1, 2, 3);
Foo(new int[] { 1, 2, 3 });
Foo(new Bar(1), new Bar(2), new Bar(3));
Foo(new Bar[] { new Bar(1), new Bar(2), new Bar(3) });
System.Threading.Thread.Sleep(20000);
}
static void Foo(params object[] objs)
{
Console.WriteLine("New call …Run Code Online (Sandbox Code Playgroud)