使用Windows API在c中异步操作:使用哪种方法以及为什么我的代码执行同步?

前端之家收集整理的这篇文章主要介绍了使用Windows API在c中异步操作:使用哪种方法以及为什么我的代码执行同步?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个C应用程序,它产生大量的输出,速度是至关重要的.该程序基本上是一个大型(8-12GB)二进制输入文件的循环,必须按顺序读取.在每次迭代中,处理读取的字节并生成输出并将其写入多个文件,但不会同时写入多个文件.因此,如果您处于生成输出的位置,并且有4个输出文件,则写入文件0或1或2或3.在迭代结束时,我现在使用fwrite()编写输出,从而等待写操作完成.输出操作总数很大,每个文件最多400万,文件输出大小从100mb到3.5GB不等.该程序在基本的多核处理器上运行.

我想在一个单独的线程中写输出,我知道这可以完成

>异步I / O.
>创建线程
> I / O完成端口

我有两类问题,即概念和特定代码.

概念性问题

什么是最好的方法.请注意,应用程序应该可以移植到Linux,但是,我不知道这对于我选择的1-3是多么重要,因为我会编写一个关于任何内核/ API特定的包装器.对我来说,最重要的标准是速度.我已经读过,选项1不太可能提高程序的性能,并且内核在任何情况下都会为i / o操作创建新的线程,所以为什么不立即使用选项(2),看起来好像很有用更容易编程(因为我没有使用选项(1)成功,请参阅下面的代码问题).

请注意,我阅读了https://stackoverflow.com/questions/3689759/how-can-i-run-a-specific-function-of-thread-asynchronously-in-c-c,但是根据应用程序的性质,我没有看到使用内容的动机.所以我希望有人能给我一些建议,在我的情况下最好.同样来自Johnson M. Hart的“Windows系统编程”一书,我知道建议使用线程,主要是因为它的简单性.但是,它也会最快吗?

代码问题

这个问题涉及到目前为止我为使异步I / O工作所做的尝试.我知道它是一个很大的代码,所以它不容易调查.无论如何,我真的很感激任何尝试.

为了减少执行时间,我尝试使用带有重叠结构的FILE_FLAGGED_OVERLAP的CreateFile()使用WINAPI通过新线程编写输出.我已经创建了一个示例程序,我试图让它工作.但是,我遇到了两个问题:

>当我删除已存在的文件时,文件仅以重叠模式打开(我尝试在不同模式下使用CreateFile(CREATE_ALWAYS,CREATE_NEW,OPEN_EXISTING),但这没有用).
>只有第一个WriteFile异步执行. WriteFile命令的其余部分是同步的.对于这个问题,我已经咨询了http://support.microsoft.com/kb/156932.似乎我遇到的问题与“对文件的任何写操作扩展其长度都是同步的”这一事实有关.我已经尝试通过增加文件大小/有效数据大小(代码中的注释区域)来解决这个问题.但是,我仍然没有让它发挥作用.我知道可能的情况是,为了最大限度地利用FILE_FLAG_NO_BUFFERING创建具有FILE_FLAG_NO_BUFFERING的异步io,但是我无法使其工作.

请注意,程序在执行路径中创建一个大约120mb的文件.另请注意,打印报表“不行”是不可取的,我希望看到“可以在后台工作”出现在我的屏幕上……这里出了什么问题?

#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ASYNC  // remove this definition to run synchronously (i.e. using fwrite)

#ifdef ASYNC
    struct _OVERLAPPED *pOverlapped;
    HANDLE *pEventH;
    HANDLE *pFile;
#else
    FILE *pFile;
#endif

#define DIM_X   100
#define DIM_Y   150000

#define _PRINTERROR(msgs)\
 {printf("file: %s,line: %d,%s",__FILE__,__LINE__,msgs);\
 fflush(stdout);\
 return 0;}    \

#define _PRINTF(msgs)\
 {printf(msgs);\
  fflush(stdout);}      \

#define _START_TIMER       \
 time_t time1,time2;       \
 clock_t clock1;        \
 time(&time1);        \
 printf("start time: %s",ctime(&time1));  \
 fflush(stdout);

#define _END_TIMER\
 time(&time2);\
 clock1 = clock();\
 printf("end time: %s",ctime(&time2));\
 printf("elapsed processor time: %.2f\n",(((float)clock1)/CLOCKS_PER_SEC));\
 fflush(stdout);

double  aio_dat[DIM_Y] = {0};

double do_compute(double A,double B,int arr_len);

int main()
{
 _START_TIMER;

 const char *pName = "test1.bin";

    DWORD dwBytesToWrite;
    BOOL bErrorFlag = FALSE;

 int j=0;
 int i=0;
 int fOverlapped=0;

    #ifdef ASYNC
     // create / open the file
        pFile=CreateFile(pName,GENERIC_WRITE,// open for writing
            0,// share write access
            NULL,// default security
            CREATE_ALWAYS,// create new/overwrite existing
         FILE_FLAG_OVERLAPPED,// | FILE_FLAG_NO_BUFFERING,// overlapped file
         NULL);           // no attr. template

  // check whether file opening was ok
     if(pFile==INVALID_HANDLE_VALUE){
   printf("%x\n",GetLastError());
   _PRINTERROR("file not opened properly\n");
  }

  // make the overlapped structure
     pOverlapped = calloc(1,sizeof(struct _OVERLAPPED)); 
  pOverlapped->Offset = 0;
  pOverlapped->OffsetHigh = 0;

   // put event handle in overlapped structure
  if(!(pOverlapped->hEvent = CreateEvent(NULL,TRUE,FALSE,NULL))){
   printf("%x\n",GetLastError());
   _PRINTERROR("error in createevent\n");
  }
 #else
  pFile = fopen(pName,"wb");
 #endif 

 // create some output 
 for(j=0;j<DIM_Y;j++){
     aio_dat[j] = do_compute(i,j,DIM_X);
 }

 // determine how many bytes should be written
  dwBytesToWrite = (DWORD)sizeof(aio_dat);

 for(i=0;i<DIM_X;i++){ // do this DIM_X times

        #ifdef ASYNC
         //if(i>0){
      //SetFilePointer(pFile,dwBytesToWrite,NULL,FILE_CURRENT);
      //if(!(SetEndOfFile(pFile))){
      // printf("%i\n",pFile);
      // _PRINTERROR("error in set end of file\n");
      //}
      //SetFilePointer(pFile,-dwBytesToWrite,FILE_CURRENT);
      //}

      // write the bytes
      if(!(bErrorFlag = WriteFile(pFile,aio_dat,pOverlapped))){
       // check whether io pending or some other error
       if(GetLastError()!=ERROR_IO_PENDING){
    printf("lasterror: %x\n",GetLastError());
    _PRINTERROR("error while writing file\n");
       }
       else{
        fOverlapped=1;
       }
      }
          else{
       // if you get here output got immediately written; bad!
       fOverlapped=0;
      }

      if(fOverlapped){   
       // do background,this msgs is what I want to see
       for(j=0;j<DIM_Y;j++){
        aio_dat[j] = do_compute(i,DIM_X);
       }
       for(j=0;j<DIM_Y;j++){
        aio_dat[j] = do_compute(i,DIM_X);
       }

       _PRINTF("can do work in background\n");
      }
      else{
       // not overlapped,this message is bad
       _PRINTF("not ok\n");
      } 

                // wait to continue
      if((WaitForSingleObject(pOverlapped->hEvent,INFINITE))!=WAIT_OBJECT_0){
       _PRINTERROR("waiting did not succeed\n");
      }

      // reset event structure
      if(!(ResetEvent(pOverlapped->hEvent))){
       printf("%x\n",GetLastError());
       _PRINTERROR("error in resetevent\n");
      }

      pOverlapped->Offset+=dwBytesToWrite;

  #else
      fwrite(aio_dat,sizeof(double),DIM_Y,pFile);
   for(j=0;j<DIM_Y;j++){
    aio_dat[j] = do_compute(i,DIM_X);
   }
   for(j=0;j<DIM_Y;j++){
    aio_dat[j] = do_compute(i,DIM_X);
   }
  #endif
 }

 #ifdef ASYNC
     CloseHandle(pFile);
  free(pOverlapped);
 #else
     fclose(pFile);
 #endif

 _END_TIMER;

 return 1;
} 

double do_compute(double A,int arr_len)
{
  int i;
  double   res = 0;
  double  *xA = malloc(arr_len * sizeof(double));
  double  *xB = malloc(arr_len * sizeof(double));

  if ( !xA || !xB )
   abort();

  for (i = 0; i < arr_len; i++) {
   xA[i] = sin(A);
   xB[i] = cos(B);
   res = res + xA[i]*xA[i];
  }

  free(xA);
  free(xB);

  return res;
}

有用的链接

> http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/cref_cls/common/cppref_asynchioC_aio_read_write_eg.htm
> http://www.ibm.com/developerworks/linux/library/l-async/?ca=dgr-lnxw02aUsingPOISIXAIOAPI
> http://www.flounder.com/asynchexplorer.htm#Asynchronous%20I/O

我知道这是一个很大的问题,我想提前感谢所有人,他们在阅读它时遇到了麻烦,甚至可能会做出回应!

您应该能够使用OVERLAPPED结构使其工作.

您处于正确的轨道:系统阻止您异步写入,因为每个WriteFile都会扩展文件的大小.但是,您正在进行错误文件大小扩展.简单地调用SetFileSize实际上不会在MFT中保留空间.使用SetFileValidData函数.这将为您的文件分配集群(请注意它们将包含磁盘所具有的任何垃圾),您应该能够并行执行WriteFile和您的计算.

我会远离FILE_FLAG_NO_BUFFERING.我认为你的并行性表现更好吗?不要阻止缓存执行其工作.

猜你在找的Windows相关文章