我有一个memcpy的问题,我似乎不明白。我在一个线程上使用memcpy,它比我从main运行时得到的时间慢3-4倍。在这两种情况下,我有2个线程正在运行一个正在等待,一个调用memcpy。你能给我任何可能的解释吗?我使用具有超线程的4核Intel机器。
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <pthread.h>
#include <algorithm>
#define MILLION 1000000
#define START_TIMER(timer) { \
gettimeofday(&(timer), NULL); \
}
#define STOP_TIMER(timer) { \
gettimeofday(&(timer), NULL); \
}
#define TIME_DIFF(timer1, timer2, total) { \
long long sec_diff = 0; \
long long usec_diff = 0; \
sec_diff = (timer2).tv_sec - (timer1).tv_sec; \
usec_diff = (timer2).tv_usec - (timer1).tv_usec; \
(total)+= (sec_diff * MILLION) + usec_diff; \
}
void copy(){
struct timeval start, stop;
long long total=0;
char buff[1024*1024];
for(int i =0;i<100;i++){
char* temp = new char[1024*1024];
START_TIMER(start);
std::copy(buff,buff+1024*1024,temp);
STOP_TIMER(stop);
TIME_DIFF(start,stop,total);
delete temp;
}
printf("%lld\n",total/100 );
}
void* mem(void* args){
copy();
pthread_exit(NULL);
}
void * nothing(void *args){
pthread_exit(NULL);
}
pthread_t thread;
int main(int argc,char* argv[]){
if(atoi(argv[1])==0){
pthread_create(&thread,NULL,nothing,NULL);
pthread_join(thread,NULL);
copy();
}
else{
pthread_create(&thread,NULL,mem,NULL);
pthread_join(thread,NULL);
}
}
感谢您的时间。我希望这不是太愚蠢。
答案 0 :(得分:0)
首先,我无法运行代码,当调用copy()
时发生线程(传递1作为参数)。 pthread_create
分配一个小的堆栈大小,并声明1MB数组buff
导致分段错误。
我改变了代码,为线程分配了一个更大的堆栈:
int main(int argc,char* argv[]){
if(atoi(argv[1])==0){
pthread_create(&thread,NULL,nothing,NULL);
pthread_join(thread,NULL);
copy();
}
else{
pthread_attr_t thread_attr;
pthread_attr_init(&thread_attr);
pthread_attr_setstacksize(&thread_attr , 20*1024*1024);
pthread_create(&thread, &thread_attr,mem,NULL);
pthread_join(thread,NULL);
}
}
这样做,并且在我的机器上的任一线程上复制之间的运行时没有区别。
但是,您的操作系统可能会导致堆争用。每当它需要分配内存时,它需要控制一个互斥锁&#39; (某种,可能是spin_lock)确保没有其他线程从堆中分配/释放。这会导致您遇到的延迟。
答案 1 :(得分:0)
调用'copy'函数时,进程的线程数似乎有所不同。当从主线程调用它时,'nothing'线程已经退出,因此该进程只有一个线程。但是当它从'mem'线程调用时,系统中实际上有两个线程。如果系统被加载或者进程的线程之间存在争用,这可能会有所不同。如果它在另一台机器或负载较少的机器上运行,则该时间差可能不存在。可以通过更改代码来验证此理论,以便您在无线程中等待并仅在调用复制函数后取消它。