c-时间切片的问题



我试图看看时间切片的效果。以及它如何消耗大量时间。事实上,我试图将某项工作划分为多个线程,看看效果如何。

我有一个双核处理器。所以两个线程可以并行运行。我试着看看我是否有一个由2个线程完成的工作w,以及我是否有由t个线程完成相同的工作,每个线程都做w/t的工作。时间切片在中起了多大作用

由于时间切片是一个耗时的过程,我预计当我使用两个线程进程或t线程进程进行相同的工作时,t线程进程所花费的时间将更多

然而,我发现事实并非如此。我试过用t=10。而且它仍然比2线程进程更快。例如,如果我必须进行10000000次迭代,那么对于两个线程进程,我将让这两个线程进行5000000次迭代,这样我们总共有10000000次迭代。如果我必须处理10个线程的过程,我会让每个线程进行1000000次迭代,这样我们总共也有10000000次。

我原以为10个线程的进程会消耗更多的时间。但事实并非如此。代码中有漏洞吗?对我来说很好

有什么建议吗?

对于一个应用程序来说,要想用比处理器多得多的线程来证明显著的、易于测量的速度减慢,你必须做到这一点:

1) 线程必须是CPU密集型的,即不阻塞I/O或彼此。如果你使用的是一个简单的计数循环(听起来像是这样),那么是的,就完成了。

2) 您必须安排每个线程处理足够大的数据,以便在上下文交换时一级缓存需要大量刷新。如果只增加一个整数,则不会发生这种刷新,并且上下文切换开销将太小(与计时器驱动的调度运行之间的间隔相比),无法轻松演示。

Windows示例数据,最小缓存刷新,i7,4/8内核:

8 tests,
400 tasks,
counting to 10000000,
using 8 threads:
Ticks: 2199
Ticks: 2184
Ticks: 2215
Ticks: 2153
Ticks: 2200
Ticks: 2215
Ticks: 2200
Ticks: 2230
Average: 2199 ms
8 tests,
400 tasks,
counting to 10000000,
using 32 threads:
Ticks: 2137
Ticks: 2121
Ticks: 2153
Ticks: 2138
Ticks: 2137
Ticks: 2121
Ticks: 2153
Ticks: 2137
Average: 2137 ms
8 tests,
400 tasks,
counting to 10000000,
using 128 threads:
Ticks: 2168
Ticks: 2106
Ticks: 2184
Ticks: 2106
Ticks: 2137
Ticks: 2122
Ticks: 2106
Ticks: 2137
Average: 2133 ms
8 tests,
400 tasks,
counting to 10000000,
using 400 threads:
Ticks: 2137
Ticks: 2153
Ticks: 2059
Ticks: 2153
Ticks: 2168
Ticks: 2122
Ticks: 2168
Ticks: 2138
Average: 2137 ms

您正在为并行版本中的每个线程依次执行10000000(1000万)x 1000次迭代和5000000(500万)x 000次迭代。根据我的经验,这足以让启动开销变得微不足道。结果对我来说似乎是正确的。

对于2个核心和2个线程,不涉及时间刻度(至少在2个工作线程之间),因为调度器足够聪明,可以将线程放在单独的核心上并保持在那里。

为了看到一些降级,您需要在缓存中移动一些内存,这样每个上下文切换实际上都会导致一些数据从缓存中移出,从而降低性能。以下是我得到的运行时间:

/a.out 2500万
线程数=2
每个线程中的迭代次数=250000000
总耗时=5.931148

./a.out 1000 500000000
线程数=1000
每个线程中的迭代次数=500000
总耗时=6.563666

./a.总计2000 500000000
线程数=2000
每个线程中的迭代次数=250000
总耗时=7.087449

这是代码。我基本上是在给定的线程中划分一个大数组,并对数组中的每个项目进行平方:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
long* array;
int length;
int threads;
void *tfunc(void *arg) {
  int n = (int)arg;
  int i;
  int j;
  int x;
  long sum = 0;
  //printf("%dn",*n);
  int start = n * (length / threads);
  int end = (n + 1) * (length / threads);
  for (i=start; i<end; i++) {
    array[i] = array[i] * array[i];
    //printf("%dn",i);
  }
  return(0);
}
double timestamp() {
  struct timeval tp;
  gettimeofday(&tp, NULL);
  return (double)tp.tv_sec + tp.tv_usec / 1000000.;
}
int main(int argc, char *argv[]) {
  int numberOfIterations = atoi(argv[2]);
  int numberOfThreads = atoi(argv[1]);
  int i;
  printf("Number of threads = %dn",numberOfThreads);
  printf("Number of iterations in each thread = %d n", numberOfIterations / numberOfThreads);
  pthread_t workerThreads[numberOfThreads];
  int *arg = &numberOfIterations;
  array = (long*)malloc(numberOfIterations * sizeof(long));
  length = numberOfIterations;
  threads = numberOfThreads;
  int result[numberOfThreads];
  double timeTaken;
  timeTaken = timestamp();
  for(i=0; i<numberOfThreads; i++) {
    result[i] = pthread_create(workerThreads+i, NULL, tfunc, (void*)i);
  }
  for(i=0; i<numberOfThreads; i++) {
    pthread_join(workerThreads[i], NULL);
  }
  timeTaken = timestamp() - timeTaken;
  printf("Total time taken = %fn", timeTaken);
  /*printf("The results aren");
  for(i=0; i<numberOfThreads; i++) {
    printf("%dn",result[i]);
  }*/
  free(array);
  exit(0);
}

您的机器上有多少CPU核心?CPU绑定线程的问题是,即使在只有一个线程的情况下,设置和调度线程可能会有开销,但如果这些线程实际上可以同时执行(而不是看起来同时执行),那么线程仍然可以产生大于开销成本的增益。

如果有多个逻辑核心,线程将并行执行。

为了检验你的假设,你需要把它们固定在一个单一的逻辑核心上。

最新更新