到目前为止,我一直在使用传统的方法来对并发方法进行基准测试,即测量多次运行的持续时间:
template <typename Functor>
double benchmark(Functor const& f, size_t nbRuns)
{
if (nbRuns == 0) { return 0.0; }
f(); // Initialize before measuring, I am not interesting in setup cost
time_t begin = time(0);
for (size_t i = 0; i != nbRuns; ++i) { f(); }
time_t end = time(0);
return difftime(end, begin);
}
Run Code Online (Sandbox Code Playgroud)
在我遇到这个问题之前看起来一切都很好和花花公子:优化掉"while(1);" 在C++ 0x中循环.
让我感到不同寻常的是,允许编译器在循环之前执行输出......我突然想知道:
什么阻止编译器
time_t end = time(0);在循环之前执行?
因为如果它这样做,那将以某种方式拧紧我的小基准代码.
虽然我们在这里,但如果在这种情况下可能发生重新排序:
怎么能阻止它呢?
除了C++之外我无法想到相关标签,如果有人认为我错过了它,请随意添加它
多年来我在C和C++中多次写过这样的无限循环,但今天是我第一次真正想到它 - 为什么条件子句为空时它是一个无限循环?人们会期望你必须写一些类似于for(;true;);获得有效无限循环的东西?
while(); 不编译也不编译 while(;);
无论如何,我喜欢for(;;);语法并经常使用它,但是将空条件块视为true是特殊情况还是在C或C++中有其他情况将空条件表达式解释为true?
最近,我发现void __builtin_assume(bool)了 clang,它可以向编译器提供有关程序状态的附加信息。这可以产生巨大的差异,例如:
#include <cstddef>
// compiles to about 80 instructions at -O3
unsigned sum(unsigned data[], size_t count) {
unsigned sum = 0;
for (size_t i = 0; i < count; ++i) {
sum += data[i];
}
return sum;
}
// compiles to about 10 instructions at -O3
unsigned sum_small(unsigned data[], size_t count) {
__builtin_assume(count <= 4);
unsigned sum = 0;
for (size_t i = 0; i < count; ++i) {
sum += data[i];
}
return …Run Code Online (Sandbox Code Playgroud) 我创建了这个程序.它没有任何兴趣,但使用处理能力.
查看输出objdump -d,即使用O3编译,我也可以看到接近结束的三个rand调用和相应的mov指令.
为什么编译器没有意识到内存不会被使用而只是替换下半部分while(1){}?我正在使用gcc,但我最感兴趣的是标准所要求的内容.
/*
* Create a program that does nothing except slow down the computer.
*/
#include <cstdlib>
#include <unistd.h>
int getRand(int max) {
return rand() % max;
}
int main() {
for (int thread = 0; thread < 5; thread++) {
fork();
}
int len = 1000;
int *garbage = (int*)malloc(sizeof(int)*len);
for (int x = 0; x < len; x++) {
garbage[x] = x;
}
while (true) …Run Code Online (Sandbox Code Playgroud) 最近我注意到在尝试为工作项目的某些代码添加一些多线程功能时,pthreads在后勤处理方面是一个巨大的痛苦......
这是场景......
我的main方法(服务器)中有一个无限循环,它产生线程来处理来自任何客户端的数据包的数据.问题是我无法让线程同时执行.他们拒绝开始执行,直到从main方法调用pthread_join(),这完全杀死了首先使用线程的整个目的(服务器需要停止执行流程,并等待线程在接收之前完成处理数据)再包了!太荒谬了.)
那么有没有办法使用pthreads并让它们实际上是多线程的?或者我最好不要使用线程,并通过停止在我的服务器中执行来调用函数来处理数据来节省额外的资源?
我想我可能每次都要诉诸...
这令人沮丧......
我做的一些示例代码如下:
// gcc threads.c -lpthread
#include <stdio.h>
#include <pthread.h>
struct point{
int x, y;
};
static void *print_point(void *point_p);
int main() {
pthread_t tid;
struct point pt = {3, 5};
printf("enter main\n");
pthread_create(&tid, NULL, print_point, &pt);
while(1){continue;}
return 0;
}
static void *print_point(void *point_p) {
struct point arg = * (struct point *) point_p;
printf("Point: (%d, %d)\n", arg.x, arg.y);
return NULL;
}
Run Code Online (Sandbox Code Playgroud)
当我运行并编译时(是的,我用-lpthread开关编译),它打印"输入主"并且不执行线程...我甚至让它运行了一段时间(起床,去了浴室,吃了一些食物),但仍然没有.
因此,由于main方法产生一个线程然后无限循环,所以线程最终应该执行......对吗?从我从测试中可以看出,main方法永远不会放弃执行它产生的线程.唯一的方法是我可以通过调用join来让它通过调用join来实现它(但是由于main将等待线程完成之后,它会失败.
是否有可能看到gcc和g ++编译过程背后发生了什么?
我有以下程序:
#include <stdio.h>
#include <unistd.h>
size_t sym1 = 100;
size_t *addr = &sym1;
size_t *arr = (size_t*)((size_t)&arr + (size_t)&addr);
int main (int argc, char **argv)
{
(void) argc;
(void) argv;
printf("libtest: addr of main(): %p\n", &main);
printf("libtest: addr of arr: %p\n", &arr);
while(1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用gcc时出错时,为什么用g ++生成二进制文件而不出错?
我正在寻找一种方法来追踪使它们表现不同的方法.
# gcc test.c -o test_app
test.c:7:1: error: initializer element is not constant
# g++ test.c -o test_app
Run Code Online (Sandbox Code Playgroud)
我认为原因可能是gcc使用cc1作为编译器而g ++使用cc1plus.
有没有办法更准确地输出实际做的?
我试过使用-v标志,但输出非常相似.是否有不同的标志传递给链接器?
比较两个编译过程并发现其中的差异的最简单方法是什么?
它可以是带或不带语句的循环吗?
while (1)
{
//Empty
}
Run Code Online (Sandbox Code Playgroud)
要么
int i = 0;
while (1)
{
i++;
}
Run Code Online (Sandbox Code Playgroud) int main(int argc, char* argv[])
{
while(1)
{
cout<<"123";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我写了这个小程序,打印"123",然后进入无限循环.但它不会在屏幕上打印任何内容.这是什么原因?
我有一个小问题,想知道是否有人可以提供帮助.我试图以最简单的方式证明我的问题.我试图通过引用传递一个对象多个线程.每个线程调用"doSomething",它是属于对象"Example"的成员函数."doSomething"函数应该递增计数器.我的gcc版本是4.4.7
问题:
为什么变量"counter"的值不会增加,尽管我通过引用传递了对象的线程函数.
代码:
#include <iostream>
#include <thread>
class Exmaple {
private:
int counter;
public:
Exmaple() {
counter = 0;
}
void doSomthing(){
counter++;
}
void print() {
std::cout << "value from A: " << counter << std::endl;
}
};
// notice that the object is passed by reference
void thread_task(Exmaple& o) {
o.doSomthing();
o.print();
}
int main()
{
Exmaple b;
while (true) {
std::thread t1(thread_task, b);
t1.join();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
value from A: 1
value from A: …Run Code Online (Sandbox Code Playgroud) 我必须使用两个线程; 一个用于对矩阵进行各种操作,另一个用于监视矩阵运算过程中各个点的虚拟内存.使用全局状态变量'flag'需要此方法.
到目前为止,我有以下内容(为简洁而留下一些):
int flag = 0;
int allocate_matrices(int dimension)
{
while (flag == 0) {} //busy wait while main prints memory state
int *matrix = (int *) malloc(sizeof(int)*dimension*dimension);
int *matrix2 = (int *) malloc(sizeof(int)*dimension*dimension);
flag = 0;
while (flag == 0) {} //busy wait while main prints memory state
// more similar actions...
}
int memory_stats()
{
while (flag == 0)
{ system("top"); flag = 1; }
}
int main()
{ //threads are created and joined for these two …Run Code Online (Sandbox Code Playgroud) 好的,我试图在c ++中的另一个线程中运行一个函数.它不需要参数,它是一个void函数.所以当我看到这个警告说:
warning: function declared 'noreturn' should not
return [-Winvalid-noreturn]
Run Code Online (Sandbox Code Playgroud)
我很惊讶.我正在使用pthread作为我的主题.这是我的功能声明:
void* checkLogKext(void*);
Run Code Online (Sandbox Code Playgroud)
这是我调用我的函数的地方:
pthread_t t1;
pthread_create(&t1, NULL, &checkLogKext, NULL);
Run Code Online (Sandbox Code Playgroud)
这是我的功能:
void* checkLogKext(void*) {
ifstream logKext("/LogKextUninstall.command");
if (logKext.is_open()) {
// Do something
}
}
Run Code Online (Sandbox Code Playgroud) 考虑到
C++11§1.10/ 24(在[intro.multithread]中)"实现可以假设任何线程最终将执行以下操作之一:
- 终止,
- 调用库I/O函数,
- 访问或修改易失性对象,或
- 执行同步操作或原子操作.
[注意:这是为了允许编译器转换,例如删除空循环,即使无法证明终止也是如此. - 尾注]
...是允许编译器优化掉以下循环的编译器:
int main(int argc, char* argv[]) {
while ( true )
fork();
}
Run Code Online (Sandbox Code Playgroud)
?
(有一些早期的讨论在(优化掉一个"while(1);"在C++ 0x中),但它似乎没有回答fork循环中调用的情况.)