我有一个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 API在c中异步操作:使用哪种方法以及为什么我的代码执行同步?的更多相关文章

  1. 使用最新的Flurry SDK和ios4重新启动应用程序

    我真的希望这对我来说只是一个愚蠢的错误.我很高兴使用Flurry但这样的事情会导致我的应用被拒绝.解决方法我写了关于这个的Flurry,他们很快回到我身边,他们会调查这个.大约一个星期后,他们回信并表示他们已经在v2.6中修复了它,现在可用了.我似乎无法重现这个问题.不是说我很棒或者什么,但我还是单枪匹马地解决了这个问题.

  2. iOS:核心图像和多线程应用程序

    我试图以最有效的方式运行一些核心图像过滤器.试图避免内存警告和崩溃,这是我在渲染大图像时得到的.我正在看Apple的核心图像编程指南.关于多线程,它说:“每个线程必须创建自己的CIFilter对象.否则,你的应用程序可能会出现意外行为.”这是什么意思?我实际上是试图在后台线程上运行我的过滤器,所以我可以在主线程上运行HUD(见下文).这在coreImage的上下文中是否有意义?

  3. ios – 多个NSPersistentStoreCoordinator实例可以连接到同一个底层SQLite持久性存储吗?

    我读过的关于在多个线程上使用CoreData的所有内容都讨论了使用共享单个NSPersistentStoreCoordinator的多个NSManagedobjectContext实例.这是理解的,我已经使它在一个应用程序中工作,该应用程序在主线程上使用CoreData来支持UI,并且具有可能需要一段时间才能运行的后台获取操作.问题是NSPersistentStoreCoordinator会对基础

  4. ios – XCode断点应该只挂起当前线程

    我需要调试多线程错误.因此,为了获得生成崩溃的条件,我需要在代码中的特定点停止一个线程,并等待另一个线程到达第二个断点.我现在遇到的问题是,如果一个线程遇到断点,则所有其他线程都被挂起.有没有办法只停止一个线程,让其他线程运行,直到它们到达第二个断点?)其他更有趣的选择:当你点击第一个断点时,你可以进入控制台并写入这应该在该断点处暂停当前上下文中的线程一小时.然后在Xcode中恢复执行.

  5. ios – 在后台线程中写入Realm后,主线程看不到更新的数据

    >清除数据库.>进行API调用以获取新数据.>将从API检索到的数据写入后台线程中的数据库中.>从主线程上的数据库中读取数据并渲染UI.在步骤4中,数据应该是最新数据,但我们没有看到任何数据.解决方法具有runloops的线程上的Realm实例,例如主线程,updatetothelatestversionofthedataintheRealmfile,因为通知被发布到其线程的runloop.在后台

  6. ios – NSURLConnectionLoader线程中的奇怪崩溃

    我们开始看到我们的应用启动时发生的崩溃.我无法重现它,它只发生在少数用户身上.例外情况是:异常类型:EXC_BAD_ACCESS代码:KERN_INVALID_ADDRESS位于0x3250974659崩溃发生在名为com.apple.NSURLConnectionLoader的线程中在调用时–[NSBlockOperationmain]这是该线程的堆栈跟踪:非常感谢任何帮助,以了解可能导致这种崩

  7. ios – 合并子上下文时的NSObjectInaccessbileExceptions

    我尝试手动重现,但失败了.是否有其他可能发生这种情况的情况,是否有处理此类问题的提示?解决方法在创建子上下文时,您可以尝试使用以下行:

  8. ios – 从后台线程调用UIKit时发出警告

    你如何处理项目中的这个问题?

  9. ios – 在SpriteKit中,touchesBegan在与SKScene更新方法相同的线程中运行吗?

    在这里的Apple文档AdvancedSceneProcessing中,它描述了更新方法以及场景的呈现方式,但没有提到何时处理输入.目前尚不清楚它是否与渲染循环位于同一个线程中,或者它是否与它并发.如果我有一个对象,我从SKScene更新方法和touchesBegan方法(在这种情况下是SKSpriteNode)更新,我是否要担心同步对我的对象的两次访问?解决方法所以几天后没有回答我设置了一些实验

  10. 如何在Xcode 4.1中调试OpenCL内核?

    我有一些OpenCL内核没有做他们应该做的事情,我很想在Xcode中调试它们.这可能吗?当我在我的内核中使用printf()时,OpenCL编译器总是给我一大堆错误.解决方法将格式字符串转换为constchar*似乎可以解决此问题.这适用于Lion:这有上述错误:

随机推荐

  1. static – 在页面之间共享数据的最佳实践

    我想知道在UWP的页面之间发送像’selectedItem’等变量的最佳做法是什么?创建一个每个页面都知道的静态全局变量类是一个好主意吗?

  2. .net – 为Windows窗体控件提供百分比宽度/高度

    WindowsForm开发的新手,但在Web开发方面经验丰富.有没有办法为Windows窗体控件指定百分比宽度/高度,以便在用户调整窗口大小时扩展/缩小?当窗口调整大小时,可以编写代码来改变控件的宽度/高度,但我希望有更好的方法,比如在HTML/CSS中.在那儿?

  3. 使用Windows Azure查询表存储数据

    我需要使用特定帐户吗?>将应用程序部署到Azure服务后,如何查询数据?GoogleAppEngine有一个数据查看器/查询工具,Azure有类似的东西吗?>您可以看到的sqlExpressintance仅在开发结构中,并且一旦您表示没有等效,所以请小心使用它.>您可以尝试使用Linqpad查询表格.看看JamieThomson的thispost.

  4. windows – SetupDiGetClassDevs是否与文档中的设备实例ID一起使用?

    有没有更好的方法可以使用DBT_DEVICEARRIVAL事件中的数据获取设备的更多信息?您似乎必须指定DIGCF_ALLCLASSES标志以查找与给定设备实例ID匹配的所有类,或者指定ClassGuid并使用DIGCF_DEFAULT标志.这对我有用:带输出:

  5. Windows Live ID是OpenID提供商吗?

    不,WindowsLiveID不是OpenID提供商.他们使用专有协议.自从他们的“测试版”期结束以来,他们从未宣布计划继续它.

  6. 如果我在代码中进行了更改,是否需要重新安装Windows服务?

    我写了一个Windows服务并安装它.现在我对代码进行了一些更改并重新构建了解决方案.我还应该重新安装服务吗?不,只需停止它,替换文件,然后重新启动它.

  7. 带有双引号的字符串回显使用Windows批处理输出文件

    我正在尝试使用Windows批处理文件重写配置文件.我循环遍历文件的行并查找我想要用指定的新行替换的行.我有一个’函数’将行写入文件问题是%Text%是一个嵌入双引号的字符串.然后失败了.可能还有其他角色也会导致失败.如何才能使用配置文件中的所有文本?尝试将所有“在文本中替换为^”.^是转义字符,因此“将被视为常规字符你可以尝试以下方法:其他可能导致错误的字符是:

  8. .net – 将控制台应用程序转换为服务?

    我正在寻找不同的优势/劣势,将我们长期使用的控制台应用程序转换为Windows服务.我们为ActiveMQ使用了一个叫做java服务包装器的东西,我相信人们告诉我你可以用它包装任何东西.这并不是说你应该用它包装任何东西;我们遇到了这个问题.控制台应用程序是一个.NET控制台应用程序,默认情况下会将大量信息记录到控制台,尽管这是可配置的.任何推荐?我们应该在VisualStudio中将其重建为服务吗?我使用“-install”/“-uninstall”开关执行此操作.例如,seehere.

  9. windows – 捕获外部程序的STDOUT和STDERR *同时*它正在执行(Ruby)

    哦,我在Windows上:-(实际上,它比我想象的要简单,这看起来很完美:…是的,它适用于Windows!

  10. windows – 当我试图批量打印变量时,为什么我得到“Echo is on”

    我想要执行一个简单的批处理文件脚本:当我在XP中运行时,它给了我预期的输出,但是当我在Vista或Windows7中运行它时,我在尝试打印值时得到“EchoisOn”.以下是程序的输出:摆脱集合表达式中的空格.等号(=)的两侧可以并且应该没有空格BTW:我通常在@echo关闭的情况下启动所有批处理文件,并以@echo结束它们,所以我可以避免将代码与批处理文件的输出混合.它只是使您的批处理文件输出更好,更清洁.

返回
顶部