小编rit*_*ter的帖子

表达式模板和C++ 11

让我们看一下表达式模板的一个特殊优点:ET可用于避免在重载运算符中出现的内存中的矢量大小临时值,如:

template<typename T>
std::vector<T> operator+(const std::vector<T>& a, const std::vector<T>& b)
{
  std::vector<T> tmp;   // vector-sized temporary
  for_each(...);
  return tmp;
}
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,此函数的return语句应用移动语义.没有矢量的副本.这是一场胜利.

但是,如果我看一个像这样的简单表达式

d = a + b + c;
Run Code Online (Sandbox Code Playgroud)

我看到上面的函数被调用两次(两者都有operator+),而最后的赋值可以用移动语义来完成.

总共执行2个循环.意思是我把一个临时的,然后读回来.对于大向量,这不属于缓存.这比表达模板更糟糕.他们可以在一个循环中完成整个过程.ET可以执行上述代码,相当于:

for(int i=0 ; i < vec_length ; ++i)
  d[i] = a[i] + b[i] + c[i];
Run Code Online (Sandbox Code Playgroud)

我想知道lambdas与移动语义或任何其他新功能一起是否可以像ET一样好.有什么想法吗?

编辑:

基本上,使用ET技术,编译器构建一个解析树,类似于代数表达式和它的类型系统.该树由内部节点和叶子节点组成.内部节点表示操作(加法,乘法等),叶节点表示对数据对象的引用.

我尝试以堆栈计算机的方式考虑整个计算过程:从操作堆栈中获取操作并从参数堆栈中提取下一个参数并评估操作.将结果放回堆栈等待操作.

为了表示这两个不同的对象(操作堆栈和数据叶堆栈),我将一个捆绑在一起std::tuple用于操作,一个 捆绑在一起std::tuple用于数据std::pair<>.最初我使用了a std:vector但导致了运行时开销.

整个过程分为两个阶段:堆栈机器初始化,其中初始化操作和参数堆栈.以及通过将配对的容器分配给向量来触发的评估阶段.

我创建了一个Vec包含私有array<int,5>(有效负载)的类,它具有一个带有"表达式"的重载赋值运算符.

operator*对于所有拍摄Vec和"表达"的组合,全局都会超负荷, 以便在我们不仅仅是的情况下也能正确处理a*b.(注意,我将这个教育示例转换为乘法 - 基本上是为了快速发现imull汇编程序.) …

c++ expression-templates c++11

34
推荐指数
2
解决办法
1万
查看次数

如何调用模板成员函数?

可能重复:
从模板函数调用的模板类的C++模板成员函数

template<class T1>
class A 
{
public:
    template<class T0>
    void foo() const {}
};

template<class T0,class T1>
void bar( const A<T1>& b )
{
    b.foo<T0>();  // This throws " expected primary-expression before ‘>’ token"
}
Run Code Online (Sandbox Code Playgroud)

我可以改成它

b->A<T1>::template foo<T0>();
Run Code Online (Sandbox Code Playgroud)

编译好.不过我也可以改成它

b.A<T1>::template foo<T0>();
Run Code Online (Sandbox Code Playgroud)

编译也很好.是吗?

如何在原始代码的意义上正确调用模板成员函数?

c++ templates

29
推荐指数
2
解决办法
2万
查看次数

何时使用std :: ref是必要的?

考虑:

std::tuple<int , const A&> func (const A& a) 
{
  return std::make_tuple( 0 , std::ref(a) );
}
Run Code Online (Sandbox Code Playgroud)

是否std::ref需要编写正确且可移植的代码?(没有它就编译好了)

背景:

如果我删除std::ref我的代码生成没有任何警告(g++-4.6 -Wall),但没有正确运行.

如有兴趣,可定义A:

struct A {
  std::array<int,2> vec;
  typedef int type_t;

  template<typename... OPs,typename... VALs>
  A& operator=(const std::pair< std::tuple<VALs...> , std::tuple<OPs...> >& e) {
    for( int i = 0 ; i < vec.size() ; ++i ) {
      vec[i] = eval( extract(i,e.first) , e.second );
    }
  }
};
Run Code Online (Sandbox Code Playgroud)

c++ portability correctness c++11

24
推荐指数
3
解决办法
8246
查看次数

为什么system()失败并显示错误代码127?

在Linux系统上,我试图通过调用在运行时调用程序system().系统调用以不等于零的返回码退出.

调用WEXITSTATUS错误代码给出"127".

根据系统的手册页,此代码表示/bin/sh无法调用:

如果/bin/sh无法执行,退出状态将是执行命令的退出状态exit(127).

我查了一下:/bin/sh是一个链接bash.bash在那儿.我可以从shell执行它.

现在,我怎么才能找出/bin/sh无法调用的原因?任何内核历史或什么?

编辑:

在这个过程非常有用的提示(见下文)之后strace -f -p <PID>.这是我在system通话中得到的:

Process 16080 detached
[pid 11779] <... select resumed> )      = ? ERESTARTNOHAND (To be restarted)
[pid 11774] <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 127}], 0, NULL) = 16080
[pid 11779] --- SIGCHLD (Child exited) @ 0 (0) ---
[pid 11779] rt_sigaction(SIGCHLD, {0x2ae0ff898ae2, [CHLD], SA_RESTORER|SA_RESTART, 0x32dd2302d0},  <unfinished …
Run Code Online (Sandbox Code Playgroud)

c c++ fork system libc++

18
推荐指数
1
解决办法
9788
查看次数

动态数组的初始化列表?

可以为静态数组的定义提供初始化列表.例:

int main()
{
  int int_static[2] = {1,2};
}
Run Code Online (Sandbox Code Playgroud)

动态数组是否可以使用类似的初始化列表?

int main()
{
  int* int_ptr = new int[2];
}
Run Code Online (Sandbox Code Playgroud)

这更接近我想要做的事情:

struct foo
{
  foo(){}
  foo(void * ptr): ptr_(ptr) {}
  void * ptr_;
};

int main()
{
  foo* foo_ptr = new foo[10];
}
Run Code Online (Sandbox Code Playgroud)

在初始化时,不应该调用默认构造函数,而是调用foo:foo(void*).

对于动态数组的静态初始化程序列表而言,如果加速器核心的实时编译只有有限的堆栈可用,但同时用(加速器编译时间=主机运行时间)静态初始化列表.

我假设没有(因为这需要编译器生成额外的代码,即将参数的值复制到堆位置).我认为c ++ 0x支持其中一些,但我无法使用它.现在我可以使用这样的结构.也许有人知道一招

最好!

c++ arrays dynamic

12
推荐指数
2
解决办法
3万
查看次数

为什么Cuda运行时在初始化时保留80 GiB虚拟内存?

我正在分析我的Cuda 4程序,结果发现在某个阶段,运行过程使用了超过80 GiB的虚拟内存.这比我预期的要多得多.在检查了内存映射随时间的演变并比较它正在执行的代码行之后,结果发现在这些简单的指令之后虚拟内存使用量突然超过80 GiB:

  int deviceCount;
  cudaGetDeviceCount(&deviceCount);
  if (deviceCount == 0) {
    perror("No devices supporting CUDA");
  }
Run Code Online (Sandbox Code Playgroud)

显然,这是第一个Cuda调用,因此运行时已初始化.在此之后,内存映射看起来像(截断):

Address           Kbytes     RSS   Dirty Mode   Mapping
0000000000400000   89796   14716       0 r-x--  prg
0000000005db1000      12      12       8 rw---  prg
0000000005db4000      80      76      76 rw---    [ anon ]
0000000007343000   39192   37492   37492 rw---    [ anon ]
0000000200000000    4608       0       0 -----    [ anon ]
0000000200480000    1536    1536    1536 rw---    [ anon ]
0000000200600000 83879936       0       0 -----    [ anon ]
Run Code Online (Sandbox Code Playgroud)

现在将这个巨大的内存区域映射到虚拟内存空间.

好吧,它可能不是一个大问题,因为除非你实际写入这个内存,否则在Linux中保留/分配内存并没有太大作用.但它真的很烦人,因为例如MPI作业必须使用作业可用的最大vmem指定.而对于Cuda工作而言,80GiB只是一个较低的边界 - 一个人也必须添加所有其他东西. …

cuda

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

如何确定套接字/节点本地的MPI等级/进程号

说,我使用MPI运行并行程序.执行命令

mpirun -n 8 -npernode 2 <prg>
Run Code Online (Sandbox Code Playgroud)

总共启动了8个流程.这是每个节点2个进程和总共4个节点.(OpenMPI 1.5).节点包含1个CPU(双核),节点之间的网络互连是InfiniBand.

现在,可以确定等级编号(或过程编号)

int myrank;
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
Run Code Online (Sandbox Code Playgroud)

这将返回0到7之间的数字.

但是,如何确定节点编号(在本例中为0到3之间的数字)和节点内的进程编号(0到1之间的编号)?

parallel-processing mpi openmpi

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

从两个枚举类创建复合类型,为STL映射做好准备

我想用两个创建一个复合类型enum classes.

enum class Color {RED, GREEN, BLUE};
enum class Shape {SQUARE, CIRCLE, TRIANGLE};

class Object {
  Color color;
  Shape shape;
public:
};
Run Code Online (Sandbox Code Playgroud)

为了Object在STL容器中使用,std::map<>我需要重载less-than运算符.但是,为了将两个枚举类压缩成一个线性索引,我不知何故需要枚举类的元素数(NoE):

friend bool operator< (const Object &lhs, const Object &rhs) {
  return NoE(Shape)*lhs.color+lhs.shape < NoE(Shape)*rhs.color+rhs.shape;
}
Run Code Online (Sandbox Code Playgroud)

如果不以一种很好的方式在程序中的两个位置输入相同的信息(元素数量),怎么做呢?(好的方式意味着没有FIRST_ELEMENT, LAST_ELEMENT,预处理器魔术等)

问题(枚举中的元素数量)类似但未解决enum classes.

我想知道在C++ 11中实现这种复合类型的最佳方法是什么.枚举类定义是否足够强大,还是有必要说:?

enum class Color {RED=0, GREEN=1, BLUE=2};
enum class Shape {SQUARE=0, CIRCLE=1, TRIANGLE=2};
Run Code Online (Sandbox Code Playgroud)

c++ enums stl c++11

11
推荐指数
2
解决办法
893
查看次数

输入函数时的SIGSEGV

只是输入一个函数会导致分段错误的原因是什么?

输入的功能如下:

21:  void eesu3(Matrix & iQ)
22:  {
Run Code Online (Sandbox Code Playgroud)

这里Matrix是一个struct.使用GDB运行时,回溯会产生:

(gdb) backtrace 
#0  eesu3 (iQ=...) at /home/.../eesu3.cc:22
#1  ...
Run Code Online (Sandbox Code Playgroud)

GDB没有透露具体是什么iQ.在...字面上有.什么可能导致这个?

海湾合作委员会:(Ubuntu/Linaro 4.6.3-1ubuntu5)4.6.3

程序内置 -O3 -g

来电者喜欢:

Matrix q;
// do some stuff with q
eesu3(q);
Run Code Online (Sandbox Code Playgroud)

这里没什么特别的

我用valgrind重新编写程序:

valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes <prgname>
Run Code Online (Sandbox Code Playgroud)

输出:

==2240== Warning: client switching stacks?  SP change: 0x7fef7ef68 --> 0x7fe5e3000
==2240==          to suppress, use: --max-stackframe=10076008 or greater
==2240== Invalid write of size 8
==2240==    at 0x14C765B: eesu3( …
Run Code Online (Sandbox Code Playgroud)

c++ linux gdb segmentation-fault

10
推荐指数
2
解决办法
3859
查看次数

objcopy将目录路径名添加到符号名称之前

我想用来objcopy将二进制形式的文本文件包含到可执行文件中.(在运行时我需要将文件作为字符串).这工作正常,直到链接器需要从符号名称中查找引用.问题是objcopy在符号名称前加上文件的路径名.由于我使用GNU Autotools发送包,这个前置路径名发生了变化,我不知道在C/C++程序中使用什么外部链接器符号.

nm libtest.a |grep textfile
textfile.o:
00001d21 D _binary__home_git_textfile_end
00001d21 A _binary__home_git_textfile_size
00000000 D _binary__home_git_textfile_start
Run Code Online (Sandbox Code Playgroud)

libtest.a 是用(从Makefile.am中提取)生成的:

SUFFIXES = .txt
.txt.$(OBJEXT):
    objcopy --input binary --output elf32-i386 --binary-architecture i386 $< $@
Run Code Online (Sandbox Code Playgroud)

我怎样才能告诉objcopy我们文件名的词干作为链接符号?或者还有另一种解决问题的方法吗?

c c++ objcopy

10
推荐指数
4
解决办法
4937
查看次数