我最近开始添加新noexcept
规范以尽可能地移动构造函数/赋值.现在我开始想知道隐式生成的成员函数的异常规范是什么样的.由于具有noexcept
移动函数允许使用更有效的代码路径(例如,在调整大小时vector
),我希望尽可能将它们声明为noexcept.我在理解标准对此有何看法时遇到了问题,因此尝试使用g ++ 4.6(with -std=c++0x
)中的以下代码来获取它:
struct foobar{};
int main()
{
foobar a, b;
std::cout<<std::boolalpha
<<noexcept(foobar())<<", "<<noexcept(foobar(a))<<", "
<<noexcept(a = b) <<", "<<noexcept(a = std::move(b))<<", "
<<noexcept(foobar(std::move(a)))<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这给了我一个输出True, True, True, False, False
,意思是默认和复制构造函数/赋值所在noexcept
,而移动操作不在哪里.
现在我的问题:
在什么情况下隐式生成(或默认)成员函数声明为noexcept
?foobar
在gcc4.6中,对于正确或简单的编译器错误,是否存在过时的行为?
我有一个std::vector
,我想要一个单独std::vector
包含原始向量的最后n个元素.除了一个接一个地插入整个矢量的循环之外,还有更简洁的方法吗?
今天我在课堂上看到了这段代码:
static const uint32_t invalid_index = ~uint32_t();
Run Code Online (Sandbox Code Playgroud)
我的问题是,uint32_t
析构函数的返回值是什么,为什么它有用?
我正在尝试熟悉c ++ 11原子,所以我尝试为线程编写一个屏障类(在有人抱怨不使用现有类之前:这更多是为了学习/自我改进,而不是由于任何实际需要).我的班级基本上看起来如下:
class barrier
{
private:
std::atomic<int> counter[2];
std::atomic<int> lock[2];
std::atomic<int> cur_idx;
int thread_count;
public:
//constructors...
bool wait();
};
Run Code Online (Sandbox Code Playgroud)
所有成员都初始化为零,除了thread_count,它保存适当的计数.我已经将wait函数实现为
int idx = cur_idx.load();
if(lock[idx].load() == 0)
{
lock[idx].store(1);
}
int val = counter[idx].fetch_add(1);
if(val >= thread_count - 1)
{
counter[idx].store(0);
cur_idx.fetch_xor(1);
lock[idx].store(0);
return true;
}
while(lock[idx].load() == 1);
return false;
Run Code Online (Sandbox Code Playgroud)
然而,当尝试使用它与两个线程(thread_count
是2)时,第一个线程进入等待循环就好了,但第二个线程没有解锁屏障(似乎它甚至没有达到int val = counter[idx].fetch_add(1);
,但我不是太确定了.但是当我使用gcc atomic-intrinsics volatile int
而不是std::atomic<int>
和写作wait
如下:
int idx = cur_idx;
if(lock[idx] == 0)
{
__sync_val_compare_and_swap(&lock[idx], 0, 1);
} …
Run Code Online (Sandbox Code Playgroud) OpenMP禁止通过异常离开openmp块的代码.因此,我正在寻找一种从openmp块获取异常的好方法,目的是在主线程中重新抛出它并在稍后处理.到目前为止,我能够提出的最好的是以下内容:
class ThreadException {
std::exception_ptr Ptr;
std::mutex Lock;
public:
ThreadException(): Ptr(nullptr) {}
~ThreadException(){ this->Rethrow(); }
void Rethrow(){
if(this->Ptr) std::rethrow_exception(this->Ptr);
}
void CaptureException() {
std::unique_lock<std::mutex> guard(this->Lock);
this->Ptr = std::current_exception();
}
};
//...
ThreadException except;
#pragma omp parallel
{
try {
//some possibly throwing code
}
catch(...) { except.CaptureException(); }
}
Run Code Online (Sandbox Code Playgroud)
虽然这很好用,但是一旦ThreadException
对象被销毁,就可以从并行部分重新抛出可能的异常,这个结构仍然有点笨拙用于放置try {}catch(...){}
每个部分并且必须手动捕获异常.
所以我的问题是:有没有人知道更优雅(更简洁)的方式(如果是这样,它看起来像什么)?
我正在尝试检查仿函数是否与给定的一组参数类型和给定的返回类型兼容(也就是说,给定的参数类型可以被隐含地转换为实际的参数类型,反之亦然的是返回类型).目前我使用以下代码:
template<typename T, typename R, template<typename U, typename V> class Comparer>
struct check_type
{ enum {value = Comparer<T, R>::value}; };
template<typename T, typename Return, typename... Args>
struct is_functor_compatible
{
struct base: public T
{
using T::operator();
std::false_type operator()(...)const;
};
enum {value = check_type<decltype(std::declval<base>()(std::declval<Args>()...)), Return, std::is_convertible>::value};
};
Run Code Online (Sandbox Code Playgroud)
check_type<T, V, Comparer>
这在大多数情况下非常struct foo{ int operator()() const;};
好用,但是当我测试无参数仿函数时,它无法编译,因为在这种情况下,两个operator()
基数显然是暧昧的,导致类似这样的事情:
error: call of '(is_functor_compatible<foo, void>::base) ()' is ambiguous
note: candidates are:
note: std::false_type is_functor_compatible<T, Return, Args>::base::operator()(...) const [with T = foo, Return …
Run Code Online (Sandbox Code Playgroud) 我目前正在使用openmp在4核phenom2上并行化程序.但是我注意到我的并行化对性能没有任何作用.当然我以为我错过了一些东西(falsesharing,通过锁定序列化......),但是我无法找到类似的东西.此外,从CPU利用率来看,程序似乎只在一个核心上执行.从我发现的sched_getcpu()
应该给我核心的Id,执行调用的线程当前安排在.所以我写了以下测试程序:
#include <iostream>
#include <sstream>
#include <omp.h>
#include <utmpx.h>
#include <random>
int main(){
#pragma omp parallel
{
std::default_random_engine rand;
int num = 0;
#pragma omp for
for(size_t i = 0; i < 1000000000; ++i) num += rand();
auto cpu = sched_getcpu();
std::ostringstream os;
os<<"\nThread "<<omp_get_thread_num()<<" on cpu "<<sched_getcpu()<<std::endl;
std::cout<<os.str()<<std::flush;
std::cout<<num;
}
}
Run Code Online (Sandbox Code Playgroud)
在我的机器上,这给出了以下输出(随机数当然会有所不同):
Thread 2 on cpu 0 num 127392776
Thread 0 on cpu 0 num 1980891664
Thread 3 on cpu 0 num 431821313
Thread 1 on cpu …
Run Code Online (Sandbox Code Playgroud) 我目前正在使用opencl为实际输入数据实现二维FFT(更具体地说是使用FFT的快速2D卷积,所以我只需要一些行为类似于足以应用卷积的东西).2D FFT在行上使用1D FFT实现,然后在cols上使用1D FFT.
为了提高效率,我试图将FFT的对称性与实际输入结合使用,以便能够计算出更小的FFT.我发现我可以将两行合并为一个,使用第一个作为实部,第二个作为虚部,在结果行上进行第一个1D FFT,然后使用对称属性构造个体的1D FFT结果那个行.所以我正在做的基本上是以下几点:
让我们f
和g
来自矩阵行.
x = f + i * g
F(x) = F(f) + i * F(g)
F(f)
和F(g)
从中提取F(x)
然而,我不能直接将结果输入到第二个1D FFT中,因为在这种情况下我不会转换整个矩阵,而是转换两个子矩阵.然而,在变换之间提取数据意味着要么存储更多数据(n/2+1
表示在实际输入上表示1D FFT结果所需的条目),要么将索引0
和索引处的n/2
元素组合成一个元素(使用相同技巧组合,因为两个数字都有保证要真实的)并使用相同数量的存储空间,但必须在我的卷积中为此做出特殊情况.
因为我尝试尽可能多地重用缓冲区(由于gpu上有限的RAM),使用更多的存储并不是一个好的解决方案.此外,我的算法无法处理矩阵大小,而矩阵大小不是2/16的倍数(从内核到内核不同).我宁愿避免引入特殊情况,因为那会使我的内核更复杂,影响效率(我已经很难最小化每个内核使用的寄存器数).
所以我的问题是,如果有一个优雅的方法来解决这个问题,这意味着如果没有使用更多的内存或某些元素的特殊情况,它会工作吗?
理想情况下,我希望能够在FFT中间分割我的组合数据来完成整个FFT,但我不确定这是否可能.
以下函数是否是线程安全的?如果它不是线程安全的,那么实际上是否有任何开销使funImpl非静态?或者编译器是否实际内联函数对象函数并完全跳过创建函数对象?
int myfun(std::array<int, 10> values)
{
static const auto funImpl = [&]() -> int
{
int sum = 0;
for (int i = 0; i < 10; ++i)
{
sum += values[i];
}
return sum;
};
return funImpl();
}
Run Code Online (Sandbox Code Playgroud)
编辑:我编辑了以下功能签名:
int myfun(const std::array<int, 10>& values)
Run Code Online (Sandbox Code Playgroud)
至:
int myfun(std::array<int, 10> values)
Run Code Online (Sandbox Code Playgroud)
所以我很清楚我不是在询问值的踏板安全性,而是函数局部静态变量funImpl的线程安全性.
我有一个人声称这条线不在C++标准中:
int i(1);
array_of_int[i] = i++;
Run Code Online (Sandbox Code Playgroud)
该人士表示,将指派1
,但我们无法知道它是否会在array_of_int[1]
或array_of_int[2]
虽然Visual Studio和大多数编译器都会在array_of_int[1]
.
他是对的吗?